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


83

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

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

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

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

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

&&ऑपरेटर की तरह है &, लेकिन मूल्यांकन करता है अपने दायां संकार्य ही अगर अपने बाएं हाथ की मूल्य संकार्य है true

||ऑपरेटर की तरह है |, लेकिन मूल्यांकन करता है अपने दायां संकार्य ही अगर अपने बाएं हाथ की मूल्य संकार्य है false

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

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


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

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


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

से 15.26.2 यौगिक असाइनमेंट ऑपरेटरों :

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

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

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

2
मैं दूसरी के लिए जाता हूं, कोई परवाह नहीं करता है: पी भी, इन सभी के बारे में सवाल 'फ़ीचर एक्स भाषा में क्यों नहीं है?' भाषा के डिजाइनरों से पूछा जाना चाहिए, हमें नहीं: पी
फेडेरिको क्लेज़ कुल्लोका

1
& = का क्या अर्थ है? कुछ एक कृपया मुझे बता सकते हैं?
तारिक

@ एरॉन: ए = ए और बी। यह प्रश्न में लिखा है
Federico klez Culloca


1
@jleedev: यह सवाल पुराना है, लेकिन इसमें अधिक वोट और आने वाले लिंक हैं। मैं कहूंगा कि अगर कोई मर्ज है, तो पुराने को इस एक में मर्ज कर दें (हां, ऐसा किया जा सकता है)।
पॉलीजेन लुब्रिकेंट्स

जवाबों:


28

कारण

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

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

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

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

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()कि हमेशा जो भी f1 () लौटाया गया है उसे मूल्य कहा जाए। यह bool isOk = f1() && f2();जहां की तरह हैf2() केवल जब कहा जाता है f1()रिटर्न true

अगर डेवलपर चाहता है f2() केवल f1()रिटर्न देते समय कॉल किया जाना है true, इसलिए ऊपर दूसरा कोड कम त्रुटि वाला है।

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

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

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

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

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, तो मैं निम्नलिखित विकल्पों की सलाह देता हूं:

// 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 ...

1
हाय @StriplingWarrior। मैंने अपने सबसे अच्छे जावा विशेषज्ञ, अपने सहयोगी यानिक के साथ जाँच की है। मैंने उस बिंदु की जांच करने के लिए उपयोग किए गए जावा कोड स्रोत का उपयोग करके अपना उत्तर अपडेट किया है। जैसा आपने कहा &और &&वैसा ही परिणाम दिया। आपके फ़ीडबैक के लिए आपका बहुत शुक्रिया। क्या आपको मेरा जवाब पसंद है? चीयर्स।
oHo

2
अगर मैं यह बहुत तेजी से करना चाहता हूं तो क्या होगा? && = से अधिक तेज़ और = होगा, यदि यह अस्तित्व में है, तो आपको if (a) a = bगति के लिए उपयोग करना चाहिए
साहसी

हाय @adventurerOK। क्षमा करें, मुझे समझ में नहीं आ रहा है कि आपका क्या मतलब है ... मुझे लगता a&=b;है if(a) a=b;कि सीपीयू रजिस्टरों के भीतर संग्रहीत मूल्यों का उपयोग करने की तुलना में तेज है हालांकि, अगर bबाहरी मेमोरी में है (कैश नहीं है), तो if(a) a=b;तेज है। क्या आपका यही मतलब है? कृपया अधिक उदाहरण कोड प्रदान करें;; मैं आपकी राय के बारे में उत्सुक हूं। फिर मिलते हैं। चीयर्स
oHo

13
जब आप कहते हैं कि मैं सहमत नहीं हूँ "और यह वह नहीं है जो हम चाहते हैं।" अगर मैं लिखता isOK &&= f2();हूं तो मैं चाहता हूं कि यह शॉर्ट सर्किट की तरह हो &&
Tor Klingberg

4
मैं आपके दावे से सहमत नहीं हूं कि ऑपरेटर त्रुटि-रहित या बेकार होंगे। यौगिक असाइनमेंट का उपयोग करना कुछ ऐसा है जो आप हमेशा के लिए एक शॉर्टकट लेते हैं A = A op B, इसलिए हर कोई पूरी तरह से जानता है कि वे क्या कर रहे हैं और खुद के निहितार्थों की देखभाल कर सकते हैं। यदि आपके कारण वास्तव में इसकी अनुपस्थिति का कारण थे, तो मैं इसे अवांछित संरक्षण के रूप में देखूंगा। हालांकि, मैं आपको लाइन जोड़ने के लिए धन्यवाद देना चाहता हूं bool isOk = f1() || f2() || f3() || f4();क्योंकि मैं खुद को देखने के लिए अंधा था।
फ्रांज बी।

17

शायद इसलिए कि ऐसा कुछ है

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

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

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


38
मुझे लगता है कि यह एक अच्छा जवाब नहीं है, क्योंकि कोई यह तर्क दे सकता है कि x() && y() ऐसा लगता है कि अभिव्यक्ति के दोनों पक्षों का मूल्यांकन करना चाहिए। स्पष्ट रूप से लोग स्वीकार करते हैं कि &&यह लघु-परिच्छेद है, इसलिए इसका अनुसरण भी करना चाहिए &&=
पॉलीजेनैलेबुलेंट

2
@ जलेदेव, सहमत। मेरा मानना ​​है कि इन स्थितियों में यह याद रखना महत्वपूर्ण है कि यह x = x && समतुल्य xComplexExpression () के बराबर नहीं है, लेकिन x = someComplexExpression () && x के समतुल्य है। प्रत्येक दूसरे असाइनमेंट ऑपरेटर के अनुरूप होने के लिए सबसे पहले दाएं हाथ का मूल्यांकन किया जाना चाहिए। और यह देखते हुए, && = का & = से भिन्न व्यवहार नहीं होगा।
PSpeed

@ पॉलीगेन यह उचित है। हालाँकि, आप जिस चीज़ से परिचित हैं, उसके आधार पर कुछ दिखता है, और मुझे लगता है कि वे कुछ नया जोड़ना नहीं चाहते थे। C / C ++ / Java / C # के बारे में एक बात मुझे पसंद है कि भावों का मूल वाक्य-विन्यास लगभग समान है।
जोश ली

1
@ पीएसपीड, आप गलत हैं। जेएलएस बहुत स्पष्ट है कि यौगिक असाइनमेंट क्या करना है। ऊपर मेरे अलावा देखें।
पॉलीजेन लुब्रिकेंट

1
@PSpeed: उस मामले में, a -= b;पूरी तरह से अलग तरह से काम करेगा a &&= b;
डेविड थॉर्नले

11

यह जावा में इस तरह है, क्योंकि यह सी में इस तरह से है।

अब सवाल यह है कि सी में ऐसा क्यों है क्योंकि कब और & amp; अलग-अलग ऑपरेटर बन गए (कुछ समय पहले बी से सी के वंश), ऑपरेटरों की विविधता को अनदेखा किया गया था।

लेकिन मेरे जवाब के दूसरे हिस्से में इसे वापस करने के लिए कोई स्रोत नहीं है।


1
मजाकिया पक्ष पर - सवाल हाल ही में सी फोरम में पूछा गया था; और यह उत्तर जुड़ा हुआ था (हालांकि डुप्लिकेट चिह्नित नहीं है) जो परिपत्र तर्क को पूरा करता है!
यूकेमोनी

6

बड़े पैमाने पर क्योंकि जावा सिंटैक्स सी (या कम से कम सी परिवार) पर आधारित है, और सी में उन सभी असाइनमेंट ऑपरेटरों को एक ही रजिस्टर पर अंकगणित या बिटवाइज़ विधानसभा निर्देशों को संकलित किया जाता है। असाइनमेंट-ऑपरेटर संस्करण अस्थायी से बचता है और शुरुआती गैर-अनुकूलन कंपाइलरों पर अधिक कुशल कोड का उत्पादन कर सकता है। तार्किक ऑपरेटर (जैसा कि उन्हें C में कहा जाता है) समकक्ष ( &&=और||= ) के पास एकल विधानसभा निर्देशों के लिए ऐसा स्पष्ट पत्राचार नहीं है; वे आमतौर पर एक परीक्षण और निर्देशों के शाखा अनुक्रम का विस्तार करते हैं।

दिलचस्प बात यह है माणिक जैसी भाषाओं करते है || = और && =।

संपादित करें: शब्दावली जावा और सी के बीच भिन्न होती है


मेरा मानना ​​है कि आप का मतलब सशर्त ऑपरेटर समकक्षों में ऐसा स्पष्ट पत्राचार नहीं है। जेएलएस शब्दावली में, बूलियन लॉजिकल ऑपरेटर हैं &, |और ^; &&और ||सशर्त संचालक हैं।
पॉलीजेनेबुलेंटेंट्स

C शब्दावली में, && और || "लॉजिकल ऑपरेटर्स" हैं, ISO 9899: 1999 में s6.5.13-14। बिटवेट ऑपरेटर केवल "तार्किक" होते हैं जब एक बिट (जावा में एक बूलियन) पर लागू किया जाता है; C में कोई एकल-बिट प्रकार नहीं है और वहां के तार्किक ऑपरेटर सभी स्केलर प्रकारों पर लागू होते हैं।
p00ya

C99 से पहले, C के पास एक boolप्रकार भी नहीं था । भाषा इतिहास में वह 20 साल है जिसमें कोई बूल नहीं है। कोई कारण नहीं था &&=। बिटवाइज ऑपरेशन काफी थे।
v.oddou

4

जावा के मूल उद्देश्यों में से एक "सरल, वस्तु उन्मुख, और परिचित" होना था। जैसा कि इस मामले पर लागू होता है, और = परिचित है (C, C ++ के पास और इस संदर्भ में परिचित का मतलब है कि जो उन दोनों को जानता है, उससे परिचित है)।

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


3

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

लिखने के बजाय

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

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

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

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


1
उस पाश के लिए आप शायद बस करना चाहते हैं if (fn(item)) { bVal = true; break; }
रेडियोडेफ

2

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

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

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


0

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

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


1
जावा << =, >> = और >>> = का समर्थन करता है, इसलिए यह कड़ाई से सच नहीं है।
यिशै

सच। मैंने उन लोगों के बारे में नहीं सोचा। मुझे लगता है कि एकमात्र स्पष्टीकरण तब कितनी बार उपयोग किया जाता है।
zzawaideh

0

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


9
लेकिन तब C / Java का मतलब कभी सुंदर होना नहीं था।
एफ़्रेम

1
मैं मुश्किल से विचार करूँगा &&=बदसूरत होने के लिए
asgs

0

और

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

&&

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

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

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


0

ब्रायन गोएट्ज़ (ओरेकल में जावा भाषा वास्तुकार) ने लिखा :

https://stackoverflow.com/q/2324549/ [इस सवाल] से पता चलता है कि इन ऑपरेटरों को रखने में दिलचस्पी है और कोई स्पष्ट तर्क नहीं है कि वे अभी तक मौजूद क्यों नहीं हैं। इसलिए सवाल यह है कि क्या जेडीके टीम ने पिछले दिनों इन ऑपरेटरों को जोड़ने पर चर्चा की है और यदि ऐसा है तो उन्हें जोड़ने के खिलाफ क्या कारण हैं?

मैं इस विशेष मुद्दे पर किसी विशेष चर्चा से अवगत नहीं हूं, लेकिन अगर कोई इसे प्रस्तावित करना चाहता था, तो इसका उत्तर होगा: यह अनुचित अनुरोध नहीं है, लेकिन यह अपना वजन नहीं बढ़ाता है।

"अपने वजन को ले जाने" को इसकी लागत और लाभों के साथ, और अन्य उम्मीदवारों की विशेषताओं के सापेक्ष इसके लागत-लाभ के अनुपात से आंका जाना चाहिए।

मुझे लगता है कि आप अनुमान लगा रहे हैं ("ब्याज है" वाक्यांश से) लागत शून्य के पास है और लाभ शून्य से अधिक है, इसलिए यह एक स्पष्ट जीत है। लेकिन यह लागत की गलत समझ को दर्शाता है; इस तरह की सुविधा भाषा की युक्ति, कार्यान्वयन, JCK और हर IDE और जावा पाठ्यपुस्तक को प्रभावित करती है। कोई तुच्छ भाषा सुविधाएँ नहीं हैं। और लाभ, जबकि नॉनजरो, बहुत छोटा है।

दूसरे, असीम रूप से कई विशेषताएं हैं जो हम कर सकते थे , लेकिन हमारे पास केवल कुछ ही वर्षों में मुट्ठी भर करने की क्षमता है (और उपयोगकर्ताओं के पास नई सुविधाओं को अवशोषित करने की एक सीमित क्षमता है।) इसलिए हमें बहुत सावधान रहना होगा, क्योंकि हम उठाते हैं, जैसा कि हम उठाते हैं। प्रत्येक सुविधा (यहां तक ​​कि एक तुच्छ प्रतीत होता है) इस बजट में से कुछ का उपभोग करती है, और हमेशा इसे दूसरों से दूर ले जाती है।
यह "यह सुविधा क्यों नहीं है", लेकिन "हम अन्य सुविधाएँ क्या नहीं करेंगे (या विलंब) इसलिए हम इसे एक कर सकते हैं, और क्या यह एक अच्छा व्यापार है?" और मैं वास्तव में यह कल्पना नहीं कर सकता कि हम जिस चीज़ पर काम कर रहे हैं, उसके खिलाफ यह एक अच्छा व्यापार है।

तो, यह "एक भयानक विचार नहीं" की पट्टी को साफ करता है (जो कि पहले से ही बहुत अच्छा है, बहुत सारे फीचर अनुरोध भी स्पष्ट नहीं हैं), लेकिन लगता है कि कभी भी "हमारे विकास बजट का बेहतर उपयोग" की पट्टी को साफ करने की संभावना नहीं है। किसी भी चीज़ से ज्यादा।"


-1

ए और बी और ए और बी एक ही चीज नहीं हैं।

a && b एक बूलियन अभिव्यक्ति है जो एक बूलियन लौटाता है, और a & b एक बिटवाइज़ एक्सप्रेशन है जो एक इंट (यदि a और b ints हैं) लौटाता है।

क्या आपको लगता है कि वे समान हैं?


1
ए और बी को हमेशा बी का मूल्यांकन करना चाहिए।
डैनियल ब्रुकनर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.