اختصار "OR-ESSIGNMENT" (| =) في جافا
-
21-09-2019 - |
سؤال
لديّ مجموعة طويلة من المقارنات التي يجب القيام بها في جافا ، وأود أن أعرف ما إذا كان واحد أو أكثر منهم ينطلقون. كانت سلسلة المقارنات طويلة وصعبة القراءة ، لذلك كسرتها لقدرة على القراءة ، وذهبت تلقائيًا لاستخدام مشغل اختصار |=
عوضا عن negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
أتوقع negativeValue
ليكون صحيحا إذا كان أي من الافتراضيu003Csomething> القيم سلبية. هل هذا صحيح؟ هل سيفعل ما أتوقع؟ لم أتمكن من رؤيته المذكورة على موقع Sun أو Stackoverflow ، ولكن يبدو أن Eclipse لا يواجه مشكلة في ذلك وتجمع الكود ويعمل.
وبالمثل ، إذا أردت إجراء العديد من التقاطعات المنطقية ، فهل يمكنني استخدام &=
بدلاً من &&
?
المحلول
ال |=
هو عامل تعيين مركب (JLS 15.26.2) للمشغل المنطقي المنطقي |
(JLS 15.22.2) ؛ لا ينبغي الخلط بينها وبين الشرطية أو ||
(JLS 15.24). هناك أيضا &=
و ^=
المقابلة لإصدار تعيين المركب من المنطق المنطقي &
و ^
على التوالى.
بمعنى آخر ، ل boolean b1, b2
, ، هذان الاثنان متكافئان:
b1 |= b2;
b1 = b1 | b2;
الفرق بين المشغلين المنطقيين (&
و |
) مقارنة بنظرائهم الشرطيين (&&
و ||
) هو أن الأول لا "دائرة قصيرة" ؛ هذا الأخير يفعل. إنه:
&
و|
دائماً تقييم كلا المعاملات&&
و||
تقييم المعامل الصحيح بشرط; ؛ يتم تقييم المعامل الصحيح فقط إذا كانت قيمتها يمكن أن تؤثر على نتيجة العملية الثنائية. هذا يعني أن المعامل الصحيح لا يتم تقييمه عندما:- المعامل الأيسر من
&&
يقيمfalse
- (لأنه بغض النظر عن المعامل الصحيح الذي يقيمه ، فإن التعبير بأكمله هو
false
)
- (لأنه بغض النظر عن المعامل الصحيح الذي يقيمه ، فإن التعبير بأكمله هو
- المعامل الأيسر من
||
يقيمtrue
- (لأنه بغض النظر عن المعامل الصحيح الذي يقيمه ، فإن التعبير بأكمله هو
true
)
- (لأنه بغض النظر عن المعامل الصحيح الذي يقيمه ، فإن التعبير بأكمله هو
- المعامل الأيسر من
لذا العودة إلى سؤالك الأصلي ، نعم ، هذا البناء صالح ، وبينما |=
ليس بالضبط اختصار مكافئ ل =
و ||
, ، إنه يحسب ما تريد. منذ الجانب الأيمن من |=
المشغل في استخدامك هو عملية مقارنة عدد صحيح بسيطة ، حقيقة أن ذلك |
لا تقصر الدائرة غير مهمة.
هناك حالات ، عندما يكون الدائرة القصير مطلوبًا ، أو حتى مطلوبًا ، لكن السيناريو الخاص بك ليس أحدها.
من المؤسف أنه على عكس بعض اللغات الأخرى ، لا تملك جافا &&=
و ||=
. تمت مناقشة هذا في السؤال لماذا لا يكون لدى Java إصدارات تعيين مركبة من المشغلين الشرطيين والشرطيين؟ (&& = ، || =).
نصائح أخرى
إنه ليس مشغل "اختصار" (أو دائرة قصيرة) في الطريقة التي || و && هم (من حيث أنهم لن يقيموا 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)
لهذه الحالة بالذات - أحاول فقط إظهار المبدأ.)
هل يمكن أن يكون لديك مجرد بيان واحد. يتم التعبير عنه على خطوط متعددة ، فإنه يقرأ تمامًا مثل رمز العينة الخاص بك ، أقل ضرورة فقط:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
لأبسط التعبيرات ، باستخدام |
يمكن أن يكون أسرع من ||
لأنه على الرغم من أنه يتجنب القيام بالمقارنة ، فهذا يعني استخدام فرع ضمنيًا وقد يكون ذلك أكثر تكلفة.
على الرغم من أنه قد يكون مبالاة لمشكلتك ، فإن الجوافة المكتبة لديها بعض بناء الجملة لطيف مع Predicate
S وهل تقييم الدائرة القصيرة من أو/و Predicate
س.
بشكل أساسي ، يتم تحويل المقارنات إلى كائنات ، وتعبئتها في مجموعة ، ثم تكرارها. من أجل أو المتوقع ، فإن أول ضربة حقيقية تعود من التكرار ، والعكس بالعكس و.
إذا كان الأمر يتعلق بالقدرة على القراءة ، فلدي مفهوم البيانات التي تم اختبارها من منطق الاختبار. عينة الكود:
// 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 );
إنه منشور قديم ولكن من أجل توفير منظور مختلف للمبتدئين ، أود تقديم مثال.
أعتقد أن حالة الاستخدام الأكثر شيوعًا لمشغل مركب مماثل ستكون +=
. أنا متأكد من أننا كتبنا جميعًا شيئًا كهذا:
int a = 10; // a = 10
a += 5; // a = 15
ما الهدف من ذلك؟ كانت النقطة لتجنب البلوغ والتخلص من الكود المتكرر.
لذلك ، السطر التالي يفعل نفس الشيء بالضبط ، وتجنب كتابة المتغير b1
مرتين في نفس الخط.
b1 |= b2;
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
|| منطقي منطقي أو
| bitwise أو
| = مشغل الواجب الشامل
السبب في أن | = لا تقصر دائرة لأنه يفعل قليلا أو ليس منطقيا أو. ذلك بالقول:
C |= 2 is same as C = C | 2