2012-04-03 5 views
24

Прогулка со мной ..Сравнивая значения Integer в Java, странное поведение

Integer x = 23; 
Integer y = 23; 

if (x == y) 
    System.out.println("what else");  // All is well as expected 
else 
    System.out.println("..."); 

Хотя

Integer x = someObject.getIndex(); 
Integer y = someOtherObject.getSomeOtherIndex(); 

if (x == y) 
    System.out.println("what else"); 
else 
    System.out.println("...");  // Prints this 

Хм ... Я пытаюсь литейным Int

int x = someObject.getIndex(); 
int y = someOtherObject.getSomeOtherIndex() 

if (x == y)  
    System.out.println("what else"); // works fine 
else 
    System.out.println("..."); 

ли они оба Целые?

System.out.println(x.getClass().getName());    // java.lang.Integer 
System.out.println(y.getClass().getName());    // java.lang.Integer 
System.out.println(someObject.getIndex());    // java.lang.Integer 
System.out.println(someOtherObject.getSomeOtherIndex()); // java.lang.Integer 

Что вы, ребята, думаете? Что бы это объясняло?

+0

возможно дубликат [Как оператор = и == оператор работает в Java ?] (http://stackoverflow.com/questions/9824053/how-operator-and-operator-works-in-java) – assylias

+0

Что делают 'getIndex();' и 'getSomeOtherIndex()' do? –

+0

Возможный дубликат [Почему 128 == 128 возвращает false, но 127 == 127 возвращает true при преобразовании в обертки Integer?] (Https://stackoverflow.com/questions/1700081/why-does-128-128-return- false-but-127-127-return-true-when-conversion-to-integ) – Tom

ответ

42

Вы сравниваете значения Integer, которые являются ссылками. Вы придумываете эти ссылки через autoboxing. Для некоторых значений (гарантируется от -128 до 127) JRE поддерживает кеш Integer объектов. Для более высоких значений это не так. От section 5.1.7 of the JLS:

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

В идеале бокс данного примитивного значения p всегда дает идентичную ссылку. На практике это может оказаться невозможным с использованием существующих методов внедрения. Правила выше - прагматичный компромисс. Последнее заключительное предложение требует, чтобы определенные общие значения всегда помещались в неразличимые объекты. Реализация может кэшировать эти, лениво или нетерпеливо. Для других значений эта формулировка запрещает любые предположения о идентичности вложенных значений на части программиста. Это позволило бы (но не требовать) совместного использования некоторых или всех этих ссылок.

Это гарантирует, что в большинстве случаев поведение будет желательным, не налагая чрезмерного штрафа за производительность, особенно на небольшие устройства. Менее ограниченные памятью реализации могут, например, кэшировать все значения char и short, а также значения int и long в диапазоне от -32K до + 32K.

Мораль: не сравнить Integer ссылки, когда вы заинтересованы в нижележащих int ценностей. Используйте .equals() или сначала получите значения int.

+2

@JAM: Да, либо приведение в 'int', вызов' intValue() 'и сравнение результатов, либо вызов' equals() '. –

+1

Хорошо круто; Спасибо, Джон! – JAM

1

Похоже, что что-то фанки с авто-боксом, когда вы используете == на двух целых числах.

Я бы предположил, что он работает нормально при использовании Integer, если вы используете метод equals()? В любом случае, по моей догадке.

Вы не используете java 1.4 или что-то не так ли?

+0

Другие ответы указывают, почему это происходит: JVM кэширует небольшие значения целых чисел. Итак, когда я сравниваю (новый Integer (12) == new Integer (12)) [возвращает true], JVM возвращает SAME-кешированный объект для обеих сторон этого значения 12. Так что, действительно, объекты одинаковы. При больших значениях создаются независимо новые объекты, и этого не происходит. – ingyhere

13

Для правильного сравнения целых чисел необходимо использовать .equals() или сравнить их примитивные значения путем литья в int или вызова intValue() на них.

== С помощью проверки ли два Целые являются же объекта, содержат ли они не в же числовое значение.

Integer a = new Integer(1); 
    Integer b = new Integer(1); 

    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false 

Отредактировано, чтобы проиллюстрировать точку Джона из JLS о Autoboxing:

Integer a = 1; 
    Integer b = 1; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //true 

против:

Integer a = 128; 
    Integer b = 128; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false 
Смежные вопросы