Почему 128 = = 128 ложно, но 127==127 истинно при сравнении целочисленных оболочек в Java?



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 являются истинными.

873   6  

6 ответов:

когда вы компилируете числовой литерал в Java и назначаете его целому числу (capital 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 может быть настроен на другое значение, с системное свойство.

-Джава.ленг.Целое число.IntegerCache.высокий=999

если вы запустите свою программу с этим системным свойством, она выведет true!

очевидный вывод: никогда не полагайтесь на две ссылки идентичны, всегда сравнивайте их с .equals() метод.

так b2.equals(b3) выведет true для всех логически равных значений b2, b3.

обратите внимание, что целочисленный кэш не существует по соображениям производительности, а скорее для comform к JLS, раздел 5.1.7; идентификатор объекта должен быть задан для значений от -128 до 127 включительно.

целое число#valueOf (int) также документирует это поведение:

этот метод, вероятно, даст значительно лучшую производительность пространства и времени путем кэширования часто запрашиваемых значений. Этот метод всегда будет кэшировать значения в диапазоне от -128 до 127 включительно и может кэшировать другие значения за пределами этого диапазона.

Автобоксинг кэширует от -128 до 127. Это указано в JLS (5.1.7).

, если значение p в коробке находится true, false, байт, символ в диапазоне от \ u0000 до \u007f или int или короткое число между -128 и 127, тогда пусть r1 и r2-результаты любых двух преобразований бокса всегда имеет место, что r1 == r2.

простое правило для запоминания при работе с объектами - использовать .равно если вы хотите проверить, являются ли два объекта "равными", используйте==, если вы хотите увидеть, указывают ли они на один и тот же экземпляр.

использование примитивных типов данных, ints, приведет к истинному в обоих случаях ожидаемому выходу.

однако, поскольку вы используете целочисленные объекты, оператор == имеет другое значение.

в контексте объектов = = проверяет, ссылаются ли переменные на одну и ту же ссылку на объект.

для сравнения значений объектов следует использовать метод equals() Е. Г.

 b2.equals(b1)

который будет указывать, является ли b2 меньше, чем b1, больше, чем, или равно (проверьте API для деталей)

это оптимизация памяти в Java обзоры.

для сохранения в памяти Java 'повторно использует' все объекты-оболочки, значения которых падение в следующих диапазонах:

все логические значения (true и false)

все байтовые значения

все символьные значения от \u0000 до \u007f (т. е. от 0 до 127 в десятичной системе счисления)

все коротко и целочисленные значения от -128 до 127.

Примечание:

  • Если вы создадите Boolean с новым Boolean (value); вы всегда получите новый объект

  • Если вы создадите строку с новой строкой (значением); вы всегда получите новый объект

  • Если вы создадите целое число с новым целым числом (значением); вы всегда получите новый объект

etc.

взгляните на целое число.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);
}       

Я написал следующее, поскольку эта проблема не просто специфична для Integer. Мой вывод заключается в том, что чаще всего, если вы используете 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

}

Comments

    Ничего не найдено.