لماذا 128 == 128 FALSE ولكن 127 == 127 صحيح عند مقارنة مغلفة عدد صحيح في جافا؟

StackOverflow https://stackoverflow.com/questions/1700081

سؤال

class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

انتاج:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

انتاج:

true

ملاحظة: الأرقام بين 128 و 127 صحيحة.

هل كانت مفيدة؟

المحلول

عند ترجمة رقم حرفي في جافا وتعيينه إلى عدد صحيح (رأس المال I) الترجمة تنبعث منها:

Integer b2 =Integer.valueOf(127)

يتم إنشاء هذا الخط من التعليمات البرمجية أيضا عند استخدام التشغيل التنفيذي.

valueOf يتم تنفيذ مثل هذه الأرقام "مجمعة"، ويعود نفس مثيل القيم أصغر من 128.

من التعليمات البرمجية المصدر Java 1.6، خط 621:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

قيمة ال high يمكن تكوينها إلى قيمة أخرى، مع خاصية النظام.

-djava.lang.inter.integercache.high = 999.

إذا قمت بتشغيل البرنامج الخاص بك مع خاصية النظام، فسوف يتم إخراجه صحيحا!

الاستنتاج الواضح: لا تعتمد أبدا على مرجعين متطابقين، دائما مقارنة معهم .equals() طريقة.

وبالتالي b2.equals(b3) سيتم طباعة صحيح لجميع القيم المتساوية منطقيا B2، B3.

لاحظ أن Integer ذاكرة التخزين المؤقت ليست هناك لأسباب الأداء، ولكنها تتوافق مع JLS، القسم 5.1.7; ؛ يجب إعطاء هوية الكائن للقيم -128 إلى 127 شاملة.

عدد صحيح # ValueOf (Int) أيضا المستندات هذا السلوك:

من المرجح أن تسفر هذه الطريقة أداء أفضل بكثير من المساحة والوقت من خلال التخزين المؤقت القيم المطلوبة بشكل متكرر. ستؤدي هذه الطريقة دائما إلى قيم ذاكرة التخزين المؤقت في النطاق -128 إلى 127، شاملة، وقد تخبئ القيم الأخرى خارج هذا النطاق.

نصائح أخرى

مخابئ الاسترذاب -128 إلى 127. تم تحديد هذا في JLS (5.1.7).

إذا كانت القيمة ب كونك محاصر صحيح، خطأ، بايت، سحر في نطاق u0000 إلى u007f، أو عدد int أو قصير بين -128 و 127، ثم دع R1 و R2 يكون نتائج أي تحويلين للملاكمة من ص. هو الحال دائما أن R1 == R2.

قاعدة بسيطة لتذكرها عند التعامل مع الكائنات - استخدام .equals إذا كنت ترغب في التحقق مما إذا كانت الكائنتين "متساويتين"، فاستخدم == عندما تريد معرفة ما إذا كانت تشير إلى نفس المثيل.

باستخدام أنواع البيانات البدائية، فإن Ints، سينتج صحيحا في كلتا الحالتين، الإخراج المتوقع.

ومع ذلك، نظرا لأنك تستخدم كائنات عدد صحيح، فإن المشغل لديه معنى مختلف.

في سياق الكائنات، == الشيكات لمعرفة ما إذا كانت المتغيرات تشير إلى نفس مرجع الكائن.

لمقارنة قيمة الكائنات التي يجب عليك استخدام الأسلوب Equals () على سبيل المثال

 b2.equals(b1)

مما سيشير إلى ما إذا كان B2 أقل من B1، أكبر من، أو يساوي (تحقق من API للحصول على التفاصيل)

إنه تحسين الذاكرة في جافا ذات الصلة.

لحفظ على الذاكرة، java 'reuses' جميع الكائنات التفاف التي تنخفض قيمها في النطاقات التالية:

جميع القيم المنطقية (صحيحة وكاذبة)

جميع القيم البايت

جميع قيم الشخصية من u0000 إلى u007f (أي 0 إلى 127 في عشري)

جميع القيم القصيرة والعددية من -128 إلى 127.

إلقاء نظرة على Integer.java، إذا كانت القيمة بين 128 و 127، فسوف تستخدم حمام السباحة المخزن مؤقتا، لذلك (Integer) 1 == (Integer) 1 في حين (Integer) 222 != (Integer) 222

 /**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}       

كتبت ما يلي لأن هذه المشكلة ليست محددة فقط حتى عدد صحيح. استنتاجي هو أنه في أغلب الأحيان إذا كنت تستخدم API بشكل غير صحيح، فإنك تراجع سلوك غير صحيح. استخدمه بشكل صحيح ويجب أن ترى السلوك الصحيح:

public static void main (String[] args) {
    Byte b1=127;
    Byte b2=127;

    Short s1=127; //incorrect should use Byte
    Short s2=127; //incorrect should use Byte
    Short s3=128;
    Short s4=128;

    Integer i1=127; //incorrect should use Byte
    Integer i2=127; //incorrect should use Byte
    Integer i3=128;
    Integer i4=128;

    Integer i5=32767; //incorrect should use Short
    Integer i6=32767; //incorrect should use Short

    Long l1=127L;           //incorrect should use Byte
    Long l2=127L;           //incorrect should use Byte
    Long l3=13267L;         //incorrect should use Short
    Long l4=32767L;         //incorrect should use Short
    Long l5=2147483647L;    //incorrect should use Integer 
    Long l6=2147483647L;    //incorrect should use Integer
    Long l7=2147483648L;
    Long l8=2147483648L;

    System.out.print(b1==b2); //true  (incorrect) Used API correctly
    System.out.print(s1==s2); //true  (incorrect) Used API incorrectly
    System.out.print(i1==i2); //true  (incorrect) Used API incorrectly
    System.out.print(l1==l2); //true  (incorrect) Used API incorrectly

    System.out.print(s3==s4); //false (correct) Used API correctly
    System.out.print(i3==i4); //false (correct) Used API correctly
    System.out.print(i5==i6); //false (correct) Used API correctly
    System.out.print(l3==l4); //false (correct) Used API correctly
    System.out.print(l7==l8); //false (correct) Used API correctly
    System.out.print(l5==l6); //false (correct) Used API incorrectly

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