Java Wrapper's Comparision
Asked Answered
M

4

5
public static void main(String[] args) {    
    System.out.println((Integer.valueOf("5000") <= Integer.valueOf("5000")));
    System.out.println((Integer.valueOf("5000") == Integer.valueOf("5000")));       
}

The above code prints true and false respectively. This is understandable, but why it prints false when we use ==.

But, when using <= (less than or equal to) why is the answer true?

Manvell answered 8/5, 2018 at 3:4 Comment(1)
possible duplicate of [How to properly compare two Integers in Java? ](#1515410)Gambrinus
G
3

To explain why the code prints such output, we might need to look into lower level:

I decompiled your code to bytecode level.

For the 1st line:

System.out.println((Integer.valueOf("5000") <= Integer.valueOf("5000")));

The bytecode is(useless information is removed):

LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;  
INVOKEVIRTUAL java/lang/Integer.intValue ()I
LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
IF_ICMPGT L1

You can see for the left part of <= , JVM use Integer.valueOf function to convert the string to a Integer object. Then use Integer.intValue function to extract the inner value of this object(also called auto-unboxing). So, for the left part, we get an int value.

The right part of <= is the same as left part.

The last line IF_ICMPGT, is to compare these two int values. So, the conclusion is if you are using <=, Java compiler will do auto-unboxing for you and compare the inner int values.

For the 2nd line:

System.out.println((Integer.valueOf("5000") == Integer.valueOf("5000")));

The bytecode is(useless information is removed):

LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
IF_ACMPNE L4

You can see the bytecode is different from the 1st line. It just convert string to Integer objects, but NOT auto-unboxing them. And because they are two individual objects, they must have different addresses(In the memory).

The last line IF_ACMPNE is going to compare the addresses of these two Integer objects. So, the conclusion is if you are using ==, Java compiler will do NOTauto-unboxing for you and compare the object addresses.

What's more

The Integer class caches the Integer objects for range -128~127. It means if you pass a string with in this range, you will get the exactly same Integer object. Below code will print true:

System.out.println((Integer.valueOf("127") == Integer.valueOf("127"))); // true
Grapevine answered 8/5, 2018 at 3:38 Comment(0)
S
2

The equality operator == between two Objects means reference equality; they must refer to the same Object as their memory addresses are the same. This applies to all wrappers as well.

Two Objects can be "equal" in value, such as having all of its fields being equal, yet occupy different memory addresses. An Integer is a wrapper Object for the primitive int.

Since an Integer (and all Wrapper objects) is an Object, a == b where a, b are Integers (not ints) will return true if a, b reference the same Integer object.

In your second System.out.println, you created two new Integer objects, (Integer.valueOf("5000"), (Integer.valueOf("5000"), where they both contain the same wrapped int values. But these Integers occupy two different memory addresses, so these two can't be reference-equal. Therefore, because they aren't reference-equal, == evaluates to False.

On the other hand, less-or-equals operator <= are not defined in Objects in general. Line Integer.valueOf("5000") <= Integer.valueOf("5000"), involves "unboxing" the Integers, and then comparing the value of its int value, and returns true if the value of the first Integer's field (of type int) equals the value of the second Integer's field. Java performs unboxing on the Integer class when comparing inequality.

Seminar answered 8/5, 2018 at 3:19 Comment(0)
J
2

When you compare wrapper classes using <=, >= Java performs unboxing and compares actual int (or double, long, etc) values between each other. So Integer.valueOf("5000") <= Integer.valueOf("5000") will work like this Integer.valueOf("5000").intValue() <= Integer.valueOf("5000").intValue() which is equivalent to 5000 <= 5000.

Judo answered 8/5, 2018 at 3:32 Comment(0)
M
0

This question is easy to answer if you check the Java docs for Integer.valueOf(String s):

public static Integer valueOf(String s) throws NumberFormatException

Returns an Integer object holding the value of the specified String. The argument is interpreted as representing a signed decimal integer, exactly as if the argument were given to the parseInt(java.lang.String) method. The result is an Integer object that represents the integer value specified by the string. In other words, this method returns an Integer object equal to the value of:

   new Integer(Integer.parseInt(s))

Since Integer.valueOf("5000") returns an Integer object instead of a primitive int and yet you are comparing the objects using ==, you get false if both Integer objects are not pointing to the same reference.

  • == checks the equality by comparing the identity of the objects.

  • .equals() checks the equality by comparing the content of the objects.

When you compare objects with <, >, <= or >=, it will give you inaccurate results because you did not and you can't perform operator overloading in Java (i.e. define custom behaviors for your operators and tell them how to compare object).

If you want to compare object, implement Comparable on the class. If you want to compare Integer object, get the primitive int value before comparing them using >, <, >= or <=:

Integer.valueOf("5000").intValue() <= Integer.valueOf("5000").intValue();  //true
Marras answered 8/5, 2018 at 4:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.