2010-12-13 1 views
19

У меня есть целые числа, которые должны быть равны (и я проверяю их по выходным данным). Но в моем if условиях Java не видит, чтобы эти переменные имели одинаковое значение.Почему Java не видит, что целые числа равны?

У меня есть следующий код:

if (pay[0]==point[0] && pay[1]==point[1]) { 
    game.log.fine(">>>>>> the same"); 
} else { 
    game.log.fine(">>>>>> different"); 
} 
game.log.fine("Compare:" + pay[0] + "," + pay[1] + " -> " + point[0] + "," + point[1]); 

И следующий результат:

FINE: >>>>>> different 
FINE: Compare:: 60,145 -> 60,145 

Вероятно, я должен добавить, что point определяется так:

Integer[] point = new Integer[2]; 

и pay нас взяли из цикла-конструктора:

for (Integer[] pay : payoffs2exchanges.keySet()) 

Таким образом, эти две переменные имеют целочисленный тип.

+3

Если у вас есть открытый ум, тогда вам может понравиться мое объяснение ... Это связано с тем, что создатели Java рояльно прищурились, когда решили создать классы-оболочки, у которых действительно жалкая производительность (у вас нет представление об отходах, сгенерированных путем обертывания * int * внутри * Integer *). Они делали это главным образом потому, что не смогли создать что-то чистое и эффективное, например, * Trove * * TLongIntHashMap *. Конечно, ожидайте, что snarky kneejerk сохранит комментарии здесь от людей, которые пили кулинарную помощь Java, объясняя, как я ошибаюсь, и как классы-оболочки являются находкой;) – SyntaxT3rr0r

+1

кстати, никогда не делайте * нового Integer [2] *, потому что вы вынуждаете создание нового объекта. ** IFF ** вы продолжаете использовать классы-оболочки, такие как * Integer * (что вам действительно не нужно, но это еще одна тема), вы хотите сделать * Integer.valueOf (2) * (кстати, что позже один ** гарантирует ** согласно спецификациям Java, повторное использование первых 256 объектов Integer от -128 до 127, но это не очень хорошо известный Java-мозг). – SyntaxT3rr0r

+0

SpoonBender: Как насчет решения Java-создателей * только * разрешить перегрузку оператора для строк? Таким образом 'Integer.valueOf (127) == Integer.valueOf (127)', но 'Integer.valueOf (128)! = Integer.valueOf (128)'! – Gabe

ответ

49

Объектов (таких как Integer s) не следует сравнивать через ==, но через .equals().

Важно понимать, что несколько различных объектов Integer могут представлять одно и то же значение int. Когда ваша программа печатает >>> different, она просто говорит, что первым объектом является не тот же объект как второй объект. (В то время как вы, вероятно, хотите, чтобы сравнить объекты на основе того, какое значение они представляют.)

Из official guide на Autoboxing:

[...] Оператор == выполняет ссылочные сравнения идентичности на выражениях Integer и сравнение равенства значений по выражениям int. [...]

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

Моя общая рекомендация заключается в использовании int вместо Integer для всех локальных переменных. В этом конкретном случае вы, кажется, сохраняете координаты в массиве из 2 элементов. Я бы предположил, что вы инкапсулируете это в класс Coordinates или аналогичный и переопределите метод equals (и hashCode) здесь.

Смотрите также

9

Если бы они были простыми int типа, он будет работать.

Integer.intValue() или compareTo(Object other) или equals(Object other) для сравнения.

4

Есть два типа отличить здесь:

  • int, примитивный целочисленный тип, который вы используете большую часть времени, но не тип объекта
  • Integer, объект обертку вокруг int который могут использоваться для использования целых чисел в API, для которых требуются объекты
1

При попытке сравнить два объекта (а целое - это объект, а не переменная), результат всегда будет таким, что t hey're не равен,

в вашем случае вы должны сравнить поля объектов (в данном случае intValue)

пытается объявить Int переменных вместо объектов Integer, это поможет

2

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

Integer i=12 ; 
Integer j=12 ; // j is pointing to same object as i do. 
if(i==j) 
    print "true"; 

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

0

Условие в

pay[0]==point[0] 

выражения, использует оператор равенства == для сравнения эталонного

Integer pay[0] 

для равенства с ссылкой

Integer point[0] 

В общем, когда значения примитивного типа (такие как int, ...) сравниваются с ==, результат верен, если оба значения идентичны. Когда ссылки (такие как Integer, String, ...) сравниваются с ==, результат верен, если обе ссылки относятся к одному и тому же объекту в памяти. Чтобы сравнить фактическое содержимое (или информацию о состоянии) объектов для равенства, необходимо вызвать метод. Таким образом, с этим выражением

Integer[] point = new Integer[2]; 

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

Например:

int a = 1; 
int b = 1; 
Integer c = 1; 
Integer d = 1; 
Integer e = new Integer(1); 

сравнить с использованием б:

a == b 

, потому что они оба значения примитива типа.

сравнить с с использованием:

a == c 

из авто-бокс функции.

для сравнения с гр е использования:

c.equals(e) 

из-за новой ссылки в переменной е.

для сравнения с с г лучше и безопасно использовать:

c.equals(d) 

из:

Как вы знаете, оператор ==, примененной к обертка объектов, только проверяет, является ли объекты имеют идентичные ячейки памяти. Следующее сравнение будет поэтому, вероятно, не в состоянии:

Integer a = 1000; 
Integer b = 1000; 
if (a == b) . . . 

Однако реализация Java может, если он выбирает, завернуть часто встречающиеся значения в идентичные объекты, и, таким образом, сравнение может добиться успеха. Эта двусмысленность - это не то, что вы хотите. Средством является вызов метода equals при сравнении объектов-оберток.