2013-02-25 4 views
9

Кто-то постулировал в какой-то теме форума, что многие люди и даже опытные разработчики Java не понимают следующий мир Java-кода.Неожиданное поведение == после postincrementation

Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1++ == i2++); 
System.out.println(i1 == i2); 

Как человек с интересом к Java, я дал свои мысли и пришел к следующему результату.

System.out.println(i1++ == i2++); 
// True, since we first check for equality and increment both variables afterwards. 

System.out.println(i1 == i2); 
// True again, since both variables are already incremented and have the value 128 

Eclipse говорит мне об обратном. Первая строка истинна, а вторая - false.

Я действительно был бы признателен за разъяснения.

Второй вопрос. Является ли эта конкретная Java или этот пример выполняется, например, для языков на языке C?

+0

попробовать выполнить 'i1.equals (i2)' – vikingsteve

+8

http://stackoverflow.com/questions/5117132/integer-wrapper-objects-share-the-same-instances-only-within-the-value-127 –

+0

Это вопрос очень похож на тот, который был отправлен @DominikKunicki –

ответ

14
Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1++ == i2++); 
// here i1 and i2 are still 127 as you expected thus true 
System.out.println(i1 == i2); 
// here i1 and i2 are 128 which are equal but not cached 
    (caching range is -128 to 127), 

В случае 2, если вы используете equals() было бы вернуться верно, как == оператора для целых работает только для кэшированных значений. а 128 находится вне диапазона кэша значения выше 128 не будет храниться в кэше, таким образом, youhave использовать equals() метод, чтобы проверить, если два целых экземпляры выше 127 истинного

ТЕСТ:

Integer i1 = 126; 
    Integer i2 = 126; 
    System.out.println(i1++ == i2++);// true 
    System.out.println(i1 == i2); //true 



Integer i1 = 126; 
     Integer i2 = 126; 
     System.out.println(i1++ == i2++);// true 
     System.out.println(i1.equals(i2)); //true 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++ == i2++);// false 
     System.out.println(i1==i2); //false 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++.equals(i2++));// true 
     System.out.println(i1.equals(i2)); //true 
+4

В качестве осторожности я считаю, что диапазон кэширования - это специфическая реализация JVM, а не часть JLS. Таким образом, это поведение не гарантирует согласованности между JVM. –

+1

@ChrisKnight Это не касается реализации, как в спецификации. [Пункт 5.1.7] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7) указывает: * «Если значение p, помещенное в поле, равно [...] int или short number между -128 и 127 (включительно), тогда пусть r1 и r2 будут результатом любых двух преобразований бокса p. Всегда бывает, что r1 == r2. "* –

+1

@ Маттиас Буэленс. Мы оба правы.Для уточнения, от -128 до 127 (включительно) гарантируется. Однако JVM может распространять этот кешированный диапазон. Дальнейший текст в вашей ссылке: «Меньшие реализации, ограниченные памятью, могут, например, кэшировать все значения char и short, а также значения int и long в диапазоне от -32K до + 32K.». –

1

As объяснил это из-за Integer caching. Для удовольствия, вы можете запустить программу с помощью следующей опции JVM:

-XX:AutoBoxCacheMax=128 

и он будет печатать правда в два раза (опция доступна на hostpot 7 - не обязательно на других виртуальных машинах).

Обратите внимание, что:

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

Итог: второй оператор печати не определен в Java и может печатать истинные или ложные в зависимости от реализации виртуальной машины Java и/или параметров виртуальной машины Java используется.

+0

Просто запустил его с этим параметром - и все равно получил False. –

+0

@AleksG Он работает с точкой доступа 7u11. – assylias

+0

С OpenJDK на 64-битной Linux это не так. –