سؤال

لديّ مجموعة طويلة من المقارنات التي يجب القيام بها في جافا ، وأود أن أعرف ما إذا كان واحد أو أكثر منهم ينطلقون. كانت سلسلة المقارنات طويلة وصعبة القراءة ، لذلك كسرتها لقدرة على القراءة ، وذهبت تلقائيًا لاستخدام مشغل اختصار |= عوضا عن 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;

لأبسط التعبيرات ، باستخدام | يمكن أن يكون أسرع من || لأنه على الرغم من أنه يتجنب القيام بالمقارنة ، فهذا يعني استخدام فرع ضمنيًا وقد يكون ذلك أكثر تكلفة.

على الرغم من أنه قد يكون مبالاة لمشكلتك ، فإن الجوافة المكتبة لديها بعض بناء الجملة لطيف مع PredicateS وهل تقييم الدائرة القصيرة من أو/و 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

البرنامج التعليمي لمشغلي جافا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top