Проверка равенства Java Wrapper

  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, мне нужно четко понять концепцию, лежащую в основе этого. Может кто-нибудь объяснить такое поведение. Спасибо.


person Warrior    schedule 19.01.2009    source источник
comment
Очень интересный вопрос, и я не знал, что Java так себя ведет. Я стараюсь использовать equals () всякий раз, когда могу, поэтому мне посчастливилось избежать этой проблемы.   -  person moffdub    schedule 19.01.2009


Ответы (5)


В 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 < / а>

person Ross    schedule 19.01.2009

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

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

person SCdF    schedule 19.01.2009

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

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

Изменить: вот соответствующий абзац из Раздел 5.1.7 Спецификации языка Java :

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

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

person A. Rex    schedule 19.01.2009

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

person tunaranch    schedule 19.01.2009

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

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

at WrapperTest.main(WrapperTest.java:5)

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

Привет

person sourcerebels    schedule 19.01.2009
comment
Я думаю, вы используете java 1.4 .. попробуйте с Java 1.5 - person Warrior; 19.01.2009