هل مضمون أن عدد صحيح جديد (i) == أنا في جافا؟
-
26-09-2019 - |
سؤال
النظر في المقتطف التالي:
int i = 99999999;
byte b = 99;
short s = 9999;
Integer ii = Integer.valueOf(9); // should be within cache
System.out.println(new Integer(i) == i); // "true"
System.out.println(new Integer(b) == b); // "true"
System.out.println(new Integer(s) == s); // "true"
System.out.println(new Integer(ii) == ii); // "false"
من الواضح لماذا سيفعل السطر الأخير دائماً مطبوعات "false"
: كانوا يستخدمون ==
مقارنة الهوية المرجعية ، و new
إرادة الكائن مطلقا يكون ==
إلى كائن موجود بالفعل.
السؤال يدور حول الأسطر الثلاثة الأولى: هل تلك المقارنات مضمون أن تكون على البدائية int
, ، مع ال Integer
تلقائيًا غير محصور؟ هل هناك حالات يكون فيها البدائي محصورًا تلقائيًا بدلاً من ذلك ، ويتم إجراء مقارنات الهوية المرجعية؟ (أي شيء سيكون بعد ذلك false
!)
المحلول
نعم. JLS §5.6.2 يحدد قواعد الترويج الرقمي الثنائي. في جزء:
عندما يطبق المشغل الترويج الرقمي الثنائي على زوج من المعاملات ، يجب أن يشير كل منها :
إذا كان أي من المعاملات من نوع مرجعي ، يتم إجراء تحويل unboxing (§5.1.8).
ينطبق الترويج الرقمي الثنائي على العديد من المشغلين الرقميين ، بما في ذلك "مشغلي المساواة العددية == و! =."
JLS §15.21.1 (يحدد مشغلو المساواة العددية == و! =):
إذا كانت معاملات مشغل المساواة كلاهما من النوع الرقمي ، أو واحد من النوع الرقمي والآخر قابل للتحويل (§5.1.8) إلى النوع الرقمي ، يتم إجراء الترويج الرقمي الثنائي على المعاملات (§5.6.2).
فى المقابل، JLS §15.21.3 (مشغلات المساواة المرجعية == و! =) توفر:
إذا كانت معاملات مشغل المساواة كلاهما من النوع المرجعي أو النوع الفارغ ، فإن العملية هي مساواة الكائن
هذا يناسب الفهم المشترك للملاكمة والملاكمة ، وهذا يتم ذلك فقط عندما يكون هناك عدم تطابق.
نصائح أخرى
سأشرح أولاً على وجه التحديد ==
هو مساواة مرجعية ، و على وجه التحديد إنها مساواة رقمية. الشروط للمساواة المرجعية أبسط ، لذلك سيتم شرحها أولاً.
JLS 15.21.3 مشغلي المساواة المرجعية ==
و !=
إذا كانت المعاملات لمشغل المساواة هي إما من النوع المرجعي أو باطل اكتب ، ثم العملية هي مساواة الكائن.
هذا ما يفسر ما يلي:
System.out.println(new Integer(0) == new Integer(0)); // "false"
كلا المعاملين Integer
, ، وهي أنواع مرجعية ، ولهذا السبب ==
هو مقارنة المساواة المرجعية ، واثنان new
الكائنات لن تكون أبدا ==
لبعضهم البعض ، ولهذا السبب يطبع false
.
ل ==
أن تكون مساواة رقمية ، يجب أن يكون أحد المعامل على الأقل نوعًا رقميًا; ؛ تم تحديد هذا على النحو التالي:
JLS 15.21.1 مشغلي المساواة العددية ==
و !=
إذا كانت معاملات مشغل المساواة على حد سواء من النوع الرقمي ، أو واحد هو من النوع الرقمي و الآخر قابل للتحويل إلى النوع الرقمي ، يتم إجراء الترويج الرقمي الثنائي على المعاملات. إذا كان النوع الذي تمت ترقيته من المعاملات
int
أوlong
, ، ثم يتم إجراء اختبار مساواة عدد صحيح ؛ إذا كان النوع الذي تمت ترقيته هوfloat or
Double` ، ثم يتم إجراء اختبار المساواة في نقطة العائمة.لاحظ أن الترويج الرقمي الثنائي يؤدي تحويل قيمة مجموعة وتحويل إلغاء التفسير.
وبالتالي ، فكر فيما يلي:
System.out.println(new Integer(0) == 0); // "true"
هذه المطبوعات true
, ، لان:
- المعامل الصحيح هو رقمي
int
يكتب - المعامل الأيسر قابلة للتحويل إلى نوع رقمي ، عن طريق إلغاء التزامن إلى
int
- وبالتالي
==
هي عملية المساواة العددية
ملخص
- إذا كان كلا المعاملين
==
و!=
هي أنواع مرجعية ، ستكون دائمًا عملية مساواة مرجعية- لا يهم ما إذا كانت المعاملات قابلة للتحويل إلى أنواع رقمية
- إذا كان أحد المعامل على الأقل نوعًا رقميًا ، فسيكون دائمًا عملية مساواة رقمية
- سيتم إجراء عملية غير مربحة تلقائية على واحد (على الأكثر!) من المعاملات إذا لزم الأمر
مراجع
- JLS 4.2. الأنواع والقيم البدائية
- "ال أنواع رقمية هي الأنواع المتكاملة وأنواع النقطة العائمة. "
- دليل لغة جافا/autoboxing
- JLS 5.1.8 تحويل unboxing
- JLS 15.21.1 مشغلي المساواة العددية
==
و!=
- JLS 15.21.3 مشغلي المساواة المرجعية
==
و!=
- JLS 5.6.2 الترويج الرقمي الثنائي