开发者

Why is this condition never satisfied?

开发者 https://www.devze.com 2022-12-29 12:32 出处:网络
I don\'t know why this condition is never satisfied: I\'m comparing two ArrayList values, and it is always false.

I don't know why this condition is never satisfied: I'm comparing two ArrayList values, and it is always false.

if ( 开发者_如何学Go(Integer) results.get(rank) == (Integer) experts.get(j))

I'm debugging and I have exactly the same 2 values: 3043 and 3043 However it doesn't work.

thanks


Use equals(), not ==. These are two different objects which represent the same value. So they are not == (different objects) but are equals() (same content).


As Uri said you need to use the method .equals() for this instead of ==.

The == operator will only check to see if the references that are returned by results.get(rank) and experts.get(j) are point to the same object (which they won't technically in this case)

There are two ways to kind of approach this. 1) If you know for a fact that experts will ALWAYS contain a reference then do the following: experts.get(j).equals(results.get(rank))

2) If you are absolutely sure that you will ALWAYS have references on both sides do the following: ((Integer)results.get(rank)).intValue() == ((Integer)experts.get(j)).intValue()

Enjoy


== will only do a value comparison for primitives.

Whenever dealing with Object types, including big-cap Integer, Long, etc. you need equals, not ==


As an alternative, you could cast to int instead of Integer if this is appropriate in your application context.


The == operator checks that two Object references are identical, not equal as we normally think. This means that for Integer types, it checks that they refer to the same Integer. If somewhere in your code you have 2 lines that create new Integers with value 3043, instead of reusing one instance, then they are not referring to the same location in memory. For your problem, it could be the case that the two collections have different object references in them because of that.

Another option, as Integer is an immutable type, is that you did not new anything, and instead maybe did a valueOf, and are aware that some implementations of Integer contain a cache of the first 128 or 256 integer values that are returned on Integer.valueOf invocations.

From OpenJDK:

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

Maybe in your code you have a String equal to "3043", and you twice invoke Integer.valueOf(thatString) to get your Integer objects. But this is mistaken as well, as you can see that at least 1 implementation will still internally new anything higher than 127, and you're back to the original problem.

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

The bottom line: unless you explicitly took a single Integer and put it into both collections yourself, don't assume they are the same object. Even if you know that they probably are the same object because you know that one JVM's implementation of Integer caches up to 4096, don't rely on that. And always check an object for equality using equals unless you truly mean to ask whether they refer to the exact same location in memory. For immutable objects like Integer and String, this is hardly ever needed.


java objects must always be compared using equals method, using == compares primitive values or actual object references, which obviously is different in this case; hence your equality never satisfies.


Because the == operator checks for object identity in the sense of the same reference, they are not compared by the value they contain but by the reference they are allocated with.

It's safe to use == with primitives because they don't have references, so they are checked for equality in the sense of same value but when working with objects (and unfortunately Integer is an object that wraps an int) it checks if they are really the same object, not if they have the same value.

For example:

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

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

if you want to keep == operator you should do

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

otherwise switch to equals operator:

// 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)))


you should not compare two references with '==' until unless you want to check whether they are same objects or not , if you want to check whether they are equal use the Object.equals() method

0

精彩评论

暂无评论...
验证码 换一张
取 消