जावा में शॉर्टकट "या असाइनमेंट" (| =) ऑपरेटर


89

मेरे पास जावा में करने के लिए तुलनाओं का एक लंबा सेट है, और मैं यह जानना चाहूंगा कि क्या उनमें से एक या अधिक सच के रूप में सामने आते हैं। तुलना का तार लंबा और पढ़ने में मुश्किल था, इसलिए मैंने इसे पठनीयता के लिए तोड़ दिया, और स्वचालित रूप |=से बजाय एक शॉर्टकट ऑपरेटर का उपयोग करने के लिए चला गया negativeValue = negativeValue || boolean

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

negativeValueयदि कोई डिफ़ॉल्ट <कुछ> मान नकारात्मक हैं, तो मैं सच होने की उम्मीद करता हूं । क्या यह मान्य है? क्या यह वही होगा जो मुझे उम्मीद है? मैं इसे सूर्य की साइट या स्टैकओवरफ़्लो पर उल्लिखित नहीं देख सका, लेकिन एक्लिप्स को इससे कोई समस्या नहीं है और कोड संकलित करता है और चलता है।


इसी तरह, अगर मैं कई तार्किक चौराहों का प्रदर्शन करना चाहता था, तो क्या मैं &=इसके बजाय उपयोग कर सकता था &&?


13
आप इसकी कोशिश क्यों नहीं करते?
रोमन

यह सामान्य बूलियन तर्क है, केवल जावा नहीं। इसलिए आप इसे अन्य स्थानों पर देख सकते हैं। और आप इसे क्यों नहीं आजमाते?
डायकम

16
@ डीकम: नहीं, यहां विशिष्ट व्यवहार है। जावा बनाने के लिए चुन सकता है । = शॉर्ट-सर्कुलेटिंग, जैसे कि यह आरएचएस का मूल्यांकन नहीं करेगा यदि एलएचएस पहले से ही सच है - लेकिन यह नहीं है।
जॉन स्कीट

2
@Jon Skeet: शॉर्ट-सर्कुलेटिंग गैर-मौजूद ||=ऑपरेटर के लिए उपयुक्त होगा , लेकिन |=बिटवाइज़ या ऑपरेटर का संयोजन रूप है।
डेविड थॉर्नले

1
@Jon Skeet: ज़रूर, लेकिन |=शॉर्ट- सर्कुलेटिंग बनाना अन्य यौगिक असाइनमेंट ऑपरेटरों के साथ असंगत होगा, क्योंकि दो बार मूल्यांकन करने के बारे में सामान्य कैविएट (यदि यह मायने रखता है) के साथ a |= b;समान नहीं होगा । ऐसा लग रहा है कि बड़े भाषा व्यवहार का निर्णय नहीं हो रहा था , इसलिए मुझे आपकी बात याद आ रही है। a = a | b;a||=
डेविड थॉर्नले

जवाबों:


204

|=एक यौगिक असाइनमेंट ऑपरेटर (है JLS 15.26.2 बूलियन तार्किक ऑपरेटर के लिए) |( JLS 15.22.2 ); सशर्त-या ||( JLS 15.24 ) के साथ भ्रमित नहीं होना चाहिए । वहाँ भी &=और ^=तार्किक बूलियन के परिसर काम संस्करण के लिए इसी &और ^क्रमशः।

दूसरे शब्दों में boolean b1, b2, इन दोनों के लिए बराबर हैं:

 b1 |= b2;
 b1 = b1 | b2;

उनके सशर्त समकक्षों ( और ) की तुलना में तार्किक ऑपरेटरों ( &और |) के बीच का अंतर यह है कि पूर्व "शॉर्टक्रीक्यूट" नहीं करता है; उत्तरार्द्ध करते हैं। अर्थात्:&&||

  • &और | हमेशा दोनों ऑपरेंड का मूल्यांकन करें
  • && तथा || सशर्त रूप से सही ऑपरेंड का मूल्यांकन करें ; सही ऑपरेंड का मूल्यांकन केवल तभी किया जाता है जब इसका मान बाइनरी ऑपरेशन के परिणाम को प्रभावित कर सकता है। इसका मतलब है कि सही ऑपरेंड का मूल्यांकन कब नहीं किया जाता है:
    • का बायाँ संचालक && मूल्यांकन करता हैfalse
      • (क्योंकि सही ऑपरेंड का मूल्यांकन करने से कोई फर्क नहीं पड़ता, पूरी अभिव्यक्ति है false)
    • का बायाँ संचालक || मूल्यांकन करता हैtrue
      • (क्योंकि सही ऑपरेंड का मूल्यांकन करने से कोई फर्क नहीं पड़ता, पूरी अभिव्यक्ति है true)

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

ऐसे मामले हैं, जब शॉर्ट सर्कुलेटिंग वांछित है, या यहां तक ​​कि आवश्यक है, लेकिन आपका परिदृश्य उनमें से एक नहीं है।

यह दुर्भाग्यपूर्ण है कि कुछ अन्य भाषाओं के विपरीत, जावा में नहीं है &&=और ||=। इस सवाल पर चर्चा की गई थी कि जावा के पास सशर्त-और सशर्त-या ऑपरेटरों के मिश्रित असाइनमेंट संस्करण क्यों नहीं हैं? (&& =, || =)


+1, बहुत गहन। यह प्रशंसनीय लगता है कि एक कंपाइलर शॉर्ट-सर्किट ऑपरेटर में अच्छी तरह से परिवर्तित हो सकता है, अगर यह निर्धारित कर सकता है कि आरएचएस का कोई दुष्प्रभाव नहीं है। उस बारे में कोई सुराग?
कार्ल

मैंने पढ़ा कि जब आरएचएस तुच्छ है और एससी आवश्यक नहीं है, तो "स्मार्ट" एससी ऑपरेटर वास्तव में थोड़ा धीमा हैं। अगर सच है, तो यह आश्चर्यचकित करने के लिए अधिक दिलचस्प है कि कुछ संकलक कुछ परिस्थितियों में एससी को एनएससी में बदल सकते हैं।
पॉलीजेन लुब्रिकेंट

@ पोलियारोपेलेब्यूट्रींट्स शॉर्ट-सर्कुलेटेड ऑपरेटरों में हुड के नीचे किसी प्रकार की एक शाखा शामिल होती है, इसलिए यदि ऑपरेटरों के साथ उपयोग किए जाने वाले सत्य मूल्यों के लिए कोई शाखा-भविष्यवाणी-अनुकूल पैटर्न नहीं है और / या उपयोग में आर्किटेक्चर अच्छा नहीं है / किसी भी शाखा की भविष्यवाणी और यह मानते हुए कि संकलक और / या वर्चुअल मशीन कोई भी संबंधित अनुकूलन स्वयं नहीं करते हैं), तो हां, SC ऑपरेटर्स गैर-शॉर्ट-सर्कुलेटिंग की तुलना में कुछ सुस्ती का परिचय देंगे। कंपाइलर का पता लगाने का सबसे अच्छा तरीका कुछ भी हो सकता है कि वह एससी बनाम एनएससी का उपयोग करके एक कार्यक्रम संकलित करे और फिर यह देखने के लिए कि क्या यह अलग है, यह देखने के लिए बाइटकोड की तुलना करें।
JAB

इसके अलावा, बिटवाइज़ या ऑपरेटर के साथ भ्रमित होने की नहीं भी है |
user253751

16

यह एक "शॉर्टकट" (या शॉर्ट-सर्कुलेटिंग) ऑपरेटर नहीं है जिस तरह से || और && हैं (इसमें वे RHS का मूल्यांकन नहीं करेंगे यदि वे पहले से ही LHS के आधार पर परिणाम जानते हैं) लेकिन यह वही करेगा जो आप काम करने के संदर्भ में चाहते हैं ।

अंतर के एक उदाहरण के रूप में, यह कोड ठीक होगा यदि textशून्य है:

boolean nullOrEmpty = text == null || text.equals("")

जबकि यह नहीं होगा:

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(जाहिर है आप "".equals(text)उस विशेष मामले के लिए कर सकते हैं - मैं सिर्फ सिद्धांत को प्रदर्शित करने की कोशिश कर रहा हूं।)


3

आप सिर्फ एक बयान दे सकते हैं। कई रेखाओं पर व्यक्त किया गया यह बिल्कुल आपके नमूना कोड की तरह पढ़ता है, केवल कम जरूरी है:

boolean negativeValue
    = defaultStock < 0 
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

सरलतम अभिव्यक्तियों के लिए, का उपयोग करने की |तुलना में तेज़ हो सकता है ||क्योंकि भले ही वह तुलना करने से बचता है इसका अर्थ है कि शाखा का उपयोग करना निहित है और यह कई गुना अधिक महंगा हो सकता है।


मैंने सिर्फ एक के साथ शुरुआत की थी, लेकिन जैसा कि मूल प्रश्न में कहा गया था कि मुझे लगता है कि "तुलना की स्ट्रिंग लंबी और पढ़ने में मुश्किल थी, इसलिए मैंने इसे पठनीयता के लिए तोड़ दिया"। इस तरफ, इस मामले में मैं व्यवहार के सीखने में अधिक रुचि रखता हूं। = इस विशेष कूट कार्य को करने की तुलना में।
डेविड मेसन

1

यद्यपि यह आपकी समस्या के लिए ओवरकिल हो सकता है, अमरूद लाइब्रेरी में Predicates के साथ कुछ अच्छा वाक्यविन्यास है और / या Predicates का शॉर्ट-सर्किट मूल्यांकन करता है ।

अनिवार्य रूप से, तुलना को वस्तुओं में बदल दिया जाता है, एक संग्रह में पैक किया जाता है, और फिर इसे पुनरावृत्त किया जाता है। के लिए या भविष्यवाणी करता है, पहला सच्चा हिट पुनरावृति से रिटर्न करता है, और इसके लिए इसके विपरीत।


1

यदि यह पठनीयता के बारे में है, तो मुझे परीक्षण तर्क से अलग किए गए परीक्षण डेटा की अवधारणा मिली है। कोड नमूना:

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

कोड अधिक क्रियात्मक और आत्म-व्याख्यात्मक लगता है। तुम भी इस तरह से विधि कॉल में एक सरणी बना सकते हैं:

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

यह 'तुलना स्ट्रिंग' की तुलना में अधिक पठनीय है, और इसमें शॉर्ट-सर्किटिंग (सरणी आवंटन और विधि कॉल की लागत पर) का प्रदर्शन लाभ भी है।

संपादित करें: और भी पठनीयता केवल varargs मापदंडों का उपयोग करके प्राप्त की जा सकती है:

विधि हस्ताक्षर होंगे:

boolean checkIfAnyNegative(DataType ... data)

और कॉल इस तरह दिख सकता है:

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );

1
ऐरे आवंटन और एक विधि कॉल शॉर्ट-सर्किटिंग के लिए एक बहुत बड़ी लागत है, जब तक कि आपको तुलनात्मक कार्यों में कुछ महंगे ऑपरेशन नहीं मिले हैं (प्रश्न में उदाहरण हालांकि सस्ता है)। यह कहने के बाद कि, अधिकांश समय कोड की स्थिरता ट्रम्प के प्रदर्शन संबंधी विचारों पर जा रही है। मैं शायद इस तरह से कुछ का उपयोग करूंगा यदि मैं अलग-अलग स्थानों के एक गुच्छा में तुलना अलग-अलग कर रहा था या 4 से अधिक मूल्यों की तुलना कर रहा था, लेकिन एक मामले के लिए यह मेरे स्वाद के लिए कुछ हद तक क्रिया है।
डेविड मेसन

@DavidMason मैं सहमत हूँ। हालांकि, ध्यान रखें, कि अधिकांश आधुनिक कैलकुलेटर कुछ मिलिस से कम में उस तरह के ओवरहेड को निगल लेंगे। व्यक्तिगत रूप से मैं प्रदर्शन के मुद्दों तक ओवरहेड के बारे में परवाह नहीं करता, जो उचित प्रतीत होता है । इसके अलावा, कोड वर्बोसिटी एक फायदा है, खासकर जब जेवाडोक JAutodoc द्वारा प्रदान या उत्पन्न नहीं किया जाता है।
Krzysztof Jabłoński

1

यह एक पुरानी पोस्ट है लेकिन शुरुआती लोगों के लिए एक अलग दृष्टिकोण प्रदान करने के लिए, मैं एक उदाहरण देना चाहूंगा।

मुझे लगता है कि एक समान कंपाउंड ऑपरेटर के लिए सबसे आम उपयोग मामला होगा +=। मुझे यकीन है कि हम सभी ने कुछ इस तरह लिखा है:

int a = 10;   // a = 10
a += 5;   // a = 15

इस बात का क्या मतलब था? यह बिंदु बॉयलरप्लेट से बचने और दोहराव कोड को खत्म करने के लिए था।

तो, अगली पंक्ति बिल्कुल वैसी ही है, चर b1को एक ही पंक्ति में दो बार टाइप करने से बचना ।

b1 |= b2;

1
ऑपरेशन और ऑपरेटर के नामों में गलतियों को दर्ज करना मुश्किल है, खासकर जब नाम लंबे होते हैं। longNameOfAccumulatorAVariable += 5; बनाम longNameOfAccumulatorAVariable = longNameOfAccumulatorVVariable + 5;
आंद्रेई

0
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;

मुझे लगता है कि मैं पसंद करूँगा negativeValue = defaultStock < 0 || defaultWholesale < 0आदि सभी बॉक्सिंग और रैपिंग की अक्षमता के अलावा यहाँ चल रहा है, मुझे यह समझना आसान नहीं है कि आपके कोड का वास्तव में क्या मतलब होगा।
जॉन स्कीट

मेरे पास और भी अधिक 4 पैरामीटर हैं और मानदंड उन सभी के लिए समान है तो मुझे अपना समाधान पसंद है, लेकिन पठनीयता के लिए मैं इसे कई पंक्तियों में अलग कर दूंगा (अर्थात सूची बनाएं, मीनू ढूंढें, 0 के साथ तुलना करें) ।
रोमन

यह तुलना की एक बड़ी संख्या के लिए उपयोगी दिखता है। इस मामले में मुझे लगता है कि स्पष्टता में कमी टाइपिंग आदि में बचत के लायक नहीं है
डेविड मेसन

0

|| तार्किक बूलियन या
| बिटवार या

| = बिटवाइन समावेशी या असाइनमेंट ऑपरेटर

कारण क्यों | = शॉर्टकर्ट नहीं करता है क्योंकि यह एक बिटवाइज़ करता है या लॉजिकल नहीं है। यानी:

C | = 2 C = C के समान है 2

जावा ऑपरेटरों के लिए ट्यूटोरियल


वहाँ कोई बिटवाइज़ या बूलियंस के साथ नहीं है! ऑपरेटर |पूर्णांक बिटवार है या तार्किक भी है या जावा भाषा विनिर्देश 15.22.2 देखें।
user85421

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