2010-05-09 2 views
1

Я не знаю, почему это условие никогда не выполняется: Я сравниваю два значения ArrayList и всегда false.Почему это условие никогда не выполняется?

if ((Integer) results.get(rank) == (Integer) experts.get(j)) 

Я отладки и у меня есть точно такие же 2 значения: 3043 и 3043 Однако это не работает.

спасибо

+0

Вы пробовали 'equals()' –

+0

Если бы вы имели дело с 'int' s, это сработало бы ... –

ответ

7

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

1

== будет выполнять только сравнение значений для примитивов.

Всякий раз, когда дело с типами объектов, в том числе большой капитализацией Integer, Long и т.д. вам нужно на равных, а не ==

3

Как сказал Ури, для этого нужно использовать метод .equals() вместо ==.

Оператор == будет проверять, будут ли ссылки, возвращаемые results.get (rank) и experts.get (j), указывают на один и тот же объект (который в этом случае не будет технически)

Существует два способа подойти к этому. 1) Если вы знаете, за то, что эксперты будут всегда содержать ссылку, то сделайте следующее: experts.get (к) .equals (results.get (ранг))

2) Если вы абсолютно уверены в том, что вы всегда будете иметь ссылки на обе стороны: ((Integer) results.get (rank)). intValue() == ((Integer) experts.get (j)). intValue()

Наслаждайтесь

0

java-объекты всегда должны сравниваться с использованием метода equals, используя ==, сравнивая примитивные значения или фактические ссылки на объекты, которые, очевидно, в этом случае различны; поэтому ваше равенство никогда не удовлетворяет.

1

== проверяет оператор, что два Object ссылки являются идентичными , не равной как мы обычно думаем. Это означает, что для типов Integer он проверяет, что они относятся к тому же Integer. Если где-то в вашем коде у вас есть две строки, которые создают новое значение Integer s со значением 3043, вместо повторного использования одного экземпляра, то они не относятся к одному и тому же местоположению в памяти. Из-за этой проблемы может возникнуть ситуация, когда из-за этого у обеих коллекций есть разные ссылки на объекты.

Другой вариант, как Integer непреложный типа, является то, что вы не new ничего, и вместо этого, может быть, сделал valueOf, и известно, что некоторые реализации Integer содержат кэш первых 128 или 256 целочисленных значений, которые возвращается на Integer.valueOf invocations.

От OpenJDK:

public static Integer valueOf(int i) 
{ 
    if (i < -128 || i > 127) { 
     return new Integer(i); 
    } 
    return valueOfCache.CACHE [i+128]; 
} 

Может быть, в вашем коде у вас есть String равно "3043", и дважды вызвать Integer.valueOf(thatString), чтобы получить ваши Integer объекты. Но это также ошибочно, так как вы можете видеть, что по крайней мере 1 реализация будет по-прежнему внутренне new чем-либо выше 127, и вы вернетесь к исходной проблеме.

Integer x = new Integer(120); // as @polygenelubricants pointed out, these two will 
Integer y = new Integer(120); // never be == equal, but .equals equal, because new 
           // creates a brand new object in memory 

Integer j = Integer.valueOf(15); // sometimes values < 128 will be cached, so j == k 
Integer k = Integer.valueOf(15); // because valueOf will return the same cached object 

Integer a = Integer.valueOf(3043); // 3043 is high enough that it probably isn't cached 
Integer b = Integer.valueOf(3043); // so b is a reference to a different Integer 

В нижней строке: если вы явно не взяли ни одного Integer и поместить его в обе коллекции себя, не предполагают, что они являются тем же объектом. Даже если вы знаете, что они, вероятно, являются одним и тем же объектом, потому что вы знаете, что одна реализация JVM Integer кэшируется до 4096, не полагайтесь на это. И всегда проверяйте объект на равенство с помощью equals, если вы действительно не хотите спросить, ссылаются ли они на то же место в памяти. Для неизменяемых объектов, таких как Integer и String, это вряд ли понадобится.

+0

' new' никогда не кэшируется : он ДОЛЖЕН вернуть новый объект. Кэширование будет противоречить всему языку Java. Что является кешируемым, например, 'valueOf',' class Integer'. Сам язык не позволит такое кэширование из «нового». – polygenelubricants

+0

Спасибо @polygenelubricants, это именно то, что я думал! – Phil

1

В качестве альтернативы, вы можете использовать значение int вместо Integer, если это необходимо в контексте вашего приложения.

0

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

Это безопасно использовать == с примитивами, потому что они не имеют ссылок, поэтому они проверяются на равенство в смысле же стоимость, но при работе с объектами (и, к сожалению Integer является объектом, который обертывание int) он проверяет если они действительно являются одним и тем же объектом, а не если они имеют одинаковое значение.

Например:

Integer x = new Integer(4); 
Integer y = x; 

//this will be true: same reference 
assert(x == y) 

если вы хотите сохранить == оператора вы должны сделать

if (results.get(rank).intValue() == experts.get(j).intValue()) 

иначе перейти к равным оператору:

// you don't need to cast them since equals will take care of checking 
//if they are of the same type 
if (results.get(rank).equals(experts.get(j))) 
0

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

Смежные вопросы