java - जावा में सशर्त-और सशर्त-या ऑपरेटरों के कंपाउंड असाइनमेंट संस्करण क्यों नहीं हैं?(&&=, ||=)




conditional-operator assignment-operator (8)

तो बूलियन पर बाइनरी ऑपरेटरों के लिए, जावा है & , | , ^ , && और ||

आइए सारांशित करें कि वे यहां संक्षेप में क्या करते हैं:

के लिए, परिणाम परिणाम true यदि दोनों ऑपरेंड मान true ; अन्यथा, परिणाम false

के लिए | , परिणाम मान false यदि दोनों ऑपरेंड मान false ; अन्यथा, परिणाम true

^ , परिणाम मान true यदि ऑपरेंड मान अलग हैं; अन्यथा, परिणाम false

&& ऑपरेटर जैसा है & उसके दाएं हाथ के ऑपरेंड का मूल्यांकन करता है केवल तभी जब उसके बाएं हाथ के ऑपरेंड का मान true

|| ऑपरेटर की तरह है | , लेकिन इसके बाएं हाथ के ऑपरेंड का मूल्य केवल तभी होता है जब उसके बाएं हाथ के ऑपरेंड का मूल्य false

अब, उनमें से 5 में से 3 में से कंपाउंड असाइनमेंट संस्करण हैं, अर्थात् |= , &= और ^= । तो मेरा सवाल स्पष्ट है: जावा क्यों नहीं प्रदान करता है &&= और ||= साथ ही? मुझे लगता है कि मुझे उन लोगों की आवश्यकता है जो मुझे चाहिए &= और |=

और मुझे नहीं लगता कि "क्योंकि यह बहुत लंबा है" एक अच्छा जवाब है, क्योंकि जावा में >>>= । इस चूक के लिए एक बेहतर कारण होना चाहिए।

15.26 असाइनमेंट ऑपरेटर से :

12 असाइनमेंट ऑपरेटर हैं; [...] = *= /= %= += -= <<= >>= >>>= &= ^= |=

एक टिप्पणी की गई थी कि अगर &&= और ||= लागू किया गया था, तो यह एकमात्र ऑपरेटर होगा जो पहले दाएं हाथ का मूल्यांकन नहीं करेगा। मुझे इस धारणा पर विश्वास है कि एक यौगिक असाइनमेंट ऑपरेटर दाएं हाथ की तरफ पहला मूल्यांकन करता है।

15.26.2 कंपाउंड असाइनमेंट ऑपरेटर से :

फॉर्म E1 op= E2 की एक यौगिक असाइनमेंट अभिव्यक्ति E1 op= E2 E1 = (T)((E1) op (E2)) बराबर है, जहां T E1 का प्रकार है, सिवाय इसके कि E1 का मूल्यांकन केवल एक बार किया जाता है।

सबूत के रूप में, निम्न स्निपेट एक NullPointerException फेंकता है, न कि ArrayIndexOutOfBoundsException

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];

कारण

ऑपरेटरों &&= और ||= जावा पर उपलब्ध नहीं हैं क्योंकि अधिकांश ऑपरेटरों के लिए ये ऑपरेटर हैं:

  • प्रवण त्रुटि
  • निकम्मा

&&= लिए उदाहरण

यदि जावा ने &&= ऑपरेटर को अनुमति दी है, तो वह कोड:

bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value

के बराबर होगा:

bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true

यह पहला कोड त्रुटि-प्रवण है क्योंकि कई डेवलपर्स को लगता है कि f2() को हमेशा एफ 1 () मूल्य लौटाया जाता है। यह bool isOk = f1() && f2(); की तरह है bool isOk = f1() && f2(); जहां f2() केवल तभी बुलाया जाता है जब f1() true लौटाता true

यदि डेवलपर f2() को केवल तभी बुलाया जाता है जब f1() true लौटाता true , इसलिए ऊपर दिया गया दूसरा कोड कम त्रुटि-प्रवण है।

अन्यथा &= पर्याप्त है क्योंकि डेवलपर f2() को हमेशा कॉल करना चाहता है:

वही उदाहरण लेकिन &=

bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value

इसके अलावा, JVM को उपरोक्त कोड को निम्न के रूप में चलाया जाना चाहिए:

bool isOk = true;
if (!f1())  isOk = false;
if (!f2())  isOk = false;  //f2() always called

तुलना करें && और परिणाम

ऑपरेटर और & के परिणाम क्या हैं & वही जब बुलियन मूल्यों पर लागू होते हैं?

आइए निम्न जावा कोड का उपयोग करके जांचें:

public class qalcdo {

    public static void main (String[] args) {
        test (true,  true);
        test (true,  false);
        test (false, false);
        test (false, true);
    }

    private static void test (boolean a, boolean b) {
        System.out.println (counter++ +  ") a=" + a + " and b=" + b);
        System.out.println ("a && b = " + (a && b));
        System.out.println ("a & b = "  + (a & b));
        System.out.println ("======================");
    }

    private static int counter = 1;
}

आउटपुट:

1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================

इसलिए हाँ हम बूलेन मानों के द्वारा && को प्रतिस्थापित कर सकते हैं ;-)

तो &&= बजाय बेहतर उपयोग &= &&=

||= लिए वही

&&= समान कारण
ऑपरेटर |= कम त्रुटि-प्रवण है ||=

यदि कोई डेवलपर f2() को कॉल नहीं करना चाहता है जब f1() true लौटाता true , तो मैं निम्नलिखित विकल्पों की सलाह देता हूं:

// here a comment is required to explain that 
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();

या:

// here the following comments are not required 
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...

' & ' और ' && ' समान नहीं हैं ' && ' एक छोटा सा कट ऑपरेशन है जो तब नहीं करेगा जब पहला ऑपरेंड झूठा होता है जबकि ' & ' वैसे भी करेगा (दोनों नंबर और बूलियन के साथ काम करता है)।

मैं सहमत हूं कि यह अस्तित्व में अधिक समझ में आता है लेकिन यह बुरा नहीं है अगर यह वहां नहीं है। मुझे लगता है कि यह वहां नहीं था क्योंकि सी में यह नहीं है।

वास्तव में क्यों नहीं सोच सकता है।


और

दोनों ऑपरेटरों की पुष्टि करता है, यह थोड़ा सा ऑपरेटर है। जावा कई bitwise ऑपरेटरों को परिभाषित करता है, जिसे पूर्णांक प्रकार, लंबे, int, लघु, चार, और बाइट पर लागू किया जा सकता है।

&&

परिणाम का मूल्यांकन बंद हो जाता है अगर परिणाम पहले झूठ का मूल्यांकन करता है क्योंकि परिणाम गलत होगा, यह एक तार्किक ऑपरेटर है। यह बूलियन पर लागू किया जा सकता है।

& & ऑपरेटर ऑपरेटर के समान है, लेकिन आपका कोड थोड़ा अधिक कुशल बना सकता है। चूंकि ऑपरेटर की तुलना में दोनों अभिव्यक्तियों को पूरी अभिव्यक्ति के लिए सत्य होना चाहिए, इसलिए पहली अभिव्यक्ति का मूल्यांकन करने का कोई कारण नहीं है यदि पहला व्यक्ति गलत लौटाता है। और ऑपरेटर हमेशा दोनों अभिव्यक्तियों का मूल्यांकन करता है। && ऑपरेटर केवल दूसरी अभिव्यक्ति का मूल्यांकन करता है यदि पहली अभिव्यक्ति सत्य है।

एक && = असाइनमेंट ऑपरेटर होने से वास्तव में भाषा में नई कार्यक्षमता नहीं मिलती है। बिटवाई ऑपरेटर का अंकगणित अधिक अभिव्यक्तिपूर्ण है, आप पूर्णतया बिटविड्थ अंकगणित कर सकते हैं, जिसमें बूलियन अंकगणित शामिल है। तार्किक ऑपरेटरों केवल बुलीयन अंकगणित कर सकते हैं।


जावा के मूल aims में से एक "सरल, ऑब्जेक्ट ओरिएंटेड, और परिचित" होना था। जैसा कि इस मामले पर लागू होता है, और = परिचित है (सी, सी ++ में यह है और इस संदर्भ में परिचित है, जो उन दोनों से परिचित है जो उन दोनों को जानते हैं)।

&& = परिचित नहीं होगा, और यह आसान नहीं होगा, इस अर्थ में कि भाषा डिजाइनर भाषा में जो भी ऑपरेटर जोड़ सकते हैं, उनके बारे में सोचना नहीं चाहते थे, इसलिए कम अतिरिक्त ऑपरेटर सरल होते हैं।


बूलियन वर्र्स, && और || के लिए शॉर्ट सर्किट मूल्यांकन का उपयोग करेंगे जबकि & और | ऐसा न करें, इसलिए आप शॉर्ट सर्किट मूल्यांकन का उपयोग करने के लिए && = और || = की अपेक्षा करेंगे। इसके लिए एक अच्छा उपयोग मामला है। विशेष रूप से यदि आप एक पाश पर फिर से चल रहे हैं, तो आप तेजी से, कुशल और terse होना चाहते हैं।

लिखने के बजाय

foreach(item in coll)
{
   bVal = bVal || fn(item); // not so elegant
}

मैं लिखना चाहता हूँ

foreach(item in coll)
{
  bVal ||= fn(item);    // elegant
}

और जानते हैं कि एक बार बीवीएल सच है, एफएन () पुनरावृत्तियों के शेष के लिए नहीं कहा जाएगा।


मैं किसी भी बेहतर कारण के बारे में नहीं सोच सकता तो 'यह अविश्वसनीय बदसूरत लग रहा है!'


रूबी में इसकी अनुमति है।

अगर मुझे लगता है, तो मैं कहूंगा कि इसका अक्सर उपयोग नहीं किया जाता है, इसलिए इसे लागू नहीं किया गया था। एक और स्पष्टीकरण यह हो सकता है कि पार्सर केवल = से पहले चरित्र को देखता है


शायद कुछ ऐसा है

x = false;
x &&= someComplexExpression();

ऐसा लगता है कि इसे x को असाइन करना चाहिए और कुछ someComplexExpression() मूल्यांकन करना चाहिए, लेकिन तथ्य यह है कि x के मान पर मूल्यांकन मूल्यांकन वाक्यविन्यास से स्पष्ट नहीं है।

इसके अलावा जावा का सिंटैक्स सी पर आधारित है, और किसी ने भी उन ऑपरेटरों को जोड़ने की दबाने की आवश्यकता नहीं देखी है। वैसे भी, यदि आप किसी भी कथन के साथ बेहतर हो जाएंगे।





compound-assignment