Тест на равенство Java Wrapper - PullRequest
20 голосов
/ 19 января 2009
  public class WrapperTest {

    public static void main(String[] args) {

        Integer i = 100;
        Integer j = 100;

        if(i == j)
            System.out.println("same");
        else
            System.out.println("not same");
    }

   }

Приведенный выше код дает вывод same при запуске, однако, если мы изменим значение i и j на 1000, выход изменится на not same. Поскольку я готовлюсь к SCJP, мне необходимо четко сформулировать эту концепцию. Может кто-нибудь объяснить это поведение. Спасибо.

Ответы [ 5 ]

19 голосов
/ 19 января 2009

В Java целые числа от -128 до 127 (включительно) обычно представлены одним и тем же экземпляром объекта Integer. Это достигается использованием внутреннего класса IntegerCache (содержится внутри класса Integer и используется, например, когда вызывается Integer.valueOf () или во время автобоксирования):

private static class IntegerCache {
    private IntegerCache(){}

    static final Integer cache[] = new Integer[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Integer(i - 128);
    }
}

Смотри также: http://www.owasp.org/index.php/Java_gotchas

6 голосов
/ 19 января 2009

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

Любое целое число вне этого диапазона не кэшируется, поэтому ссылки не совпадают.

5 голосов
/ 19 января 2009

@ tunaranch правильный. Это также та же проблема, что и в этом Python вопросе . Суть в том, что Java сохраняет объект для целых чисел от -128 до 127 (Python делает от -5 до 256) и возвращает один и тот же объект каждый раз, когда вы его запрашиваете. Если вы попросите Integer за пределами этого фиксированного диапазона, он будет каждый раз давать вам новый объект.

(Напомним, что == возвращает, являются ли два объекта на самом деле одинаковыми, тогда как equals сравнивает их содержимое.)

Редактировать : Вот соответствующий параграф из Раздел 5.1.7 Спецификация языка Java :

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

Обратите внимание, что это также описывает, что происходит с другими типами.

4 голосов
/ 19 января 2009

Это связано с равенством и автобоксом: http://web.archive.org/web/20090220142800/http://davidflanagan.com/2004/02/equality-and-autoboxing.html

0 голосов
/ 19 января 2009

Ваш код не компилируется. Вот что я получаю:

Исключение в потоке "main" java.lang.Error: Нерешенные проблемы компиляции: Несоответствие типов: невозможно преобразовать из целого в целое Несоответствие типов: невозможно преобразовать из целого числа в целое число

at WrapperTest.main(WrapperTest.java:5)

Переменные i и j являются экземплярами объекта Integer. Не сравнивайте экземпляры объекта с помощью оператора «==», вместо этого используйте метод «равно».

Привет

...