Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to compare immutable objects in Java using == instead of equals

Consider two references of type Integer that call the static factory method valueOf as shown below:-

    Integer a = Integer.valueOf("10"); 
    Integer b = Integer.valueOf("10"); 

Considering that Integer is immutable, is it ok to compare a and b using == instead of using equals method. I am guessing that the valueOf method makes sure that only one instance of Integer with the value 10 is created and a reference to this instance is returned for every Integer created with a value 10.

In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?

Edit: The Integer class was used just as an example. I am aware thar Intgers upto 127 will return true if they are compared using ==. What i need to know is that when l create my own immutable class, say MyImmutable with a method create() that will ensure that no duplicate MyImmutable objects are created, will it be ok if I compare 2 MyImmutable references created using the create method by using == instead of equals.

like image 795
Chetan Kinger Avatar asked Jun 10 '12 17:06

Chetan Kinger


1 Answers

No, that's not safe in general. The == operator compares the references, not the values.

Using == happens to work for integers between -128 and 127, but not for other integers. The following code demonstrates that == won't always work:

Integer a = Integer.valueOf(10); 
Integer b = Integer.valueOf(10); 
System.out.println(a == b);

true

Integer c = Integer.valueOf(1000); 
Integer d = Integer.valueOf(1000); 
System.out.println(c == d);

false

See it working online: ideone

The explanation for this behaviour lies in the implementation of Integer.valueOf:

public static Integer valueOf(int i) {
     final int offset = 128;
     if (i >= -128 && i <= 127) { // must cache
         return IntegerCache.cache[i + offset];
     }
     return new Integer(i);
 }

source

Not also that the standard requires that boxing integers for small inputs (-128 to 127) gives objects with equal references.

5.1.7 Boxing Conversion

If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

However the standard makes no such guarantees for integers outside this range.


In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?

As shown above, it won't work in general. But if you ensure that two immutable objects with the same value always have the same reference, then yes, it could work. However there are some rules you must follow carefully:

  • The constructor must not be public.
  • Every object you create via the static method must be cached.
  • Every time you are asked to create an object you must first check the cache to see if you have already created an object with the same value.
like image 119
Mark Byers Avatar answered Nov 10 '22 00:11

Mark Byers