Firdous Amir
Firdous Amir

Reputation: 1303

Integer Enum and Unboxing

public class Document{
    private Integer status;

    // get()/set()
}

Then an enum:

public enum DocumentStatusEnum {

        ACTIVE_DOCUMENT(2060),CANCELLED_DOCUMENT(2061),DRAFT_DOCUMENT(2062),PROCESSED_DOCUMENT(2063);

        private final Integer value;

        private DocumentStatusEnum(Integer value){
            this.value = value;
        }
        public Integer getValue(){
            return value;
        }
    }

In a method I'm using the above method as below:

Document d = new Document();
d.setStatus(2063);
if (d.getStatus() == DocumentStatusEnum.PROCESSED_DOCUMENT.getValue()){
{
       // print true;
    }
    else{
       // print false;
    }

I get true here. Looks alright. In the same method, After couple of lines, I do this:

d.setStatus(2060)
if (d.getStatus() == DocumentStatusEnum.ACTIVE_DOCUMENT.getValue()){
   // print true
}
else{
   // print false

}

I get a false. I researched and found something about caching and boxing features in Java. I converted the enum definition as this:

public enum DocumentStatusEnum {

    ACTIVE_DOCUMENT(2060),CANCELLED_DOCUMENT(2061),DRAFT_DOCUMENT(2062),PROCESSED_DOCUMENT(2063);

    private final int value;

    private DocumentStatusEnum(int value){
        this.value = value;
    }
    public int getValue(){
        return value;
    }
}

Now, no issues. I get true in both cases.

Question is why this happening? I feel this behaviour is extremely unstable. It's a large application I'm dealing with and I'm using Integer == Integer comparison every where. Am I safe here?

Upvotes: 1

Views: 932

Answers (2)

Daniel Pryden
Daniel Pryden

Reputation: 60997

Integer extends Object and therefore == is defined as reference equality, not value equality.

When comparing Integer with int, the Integer will be unboxed to an int, and the two operands will be compared for value equality. (Unless the Integer value is null, in which case NullPointerException will be thrown instead.) But Integer == Integer is never safe.

That said, because by default the runtime pre-allocates Integer instances for small integers (-128 through 127, according to the OpenJDK source), you can often get Integer == Integer to work for small values. But that behavior does not hold for larger values, and it is never required to hold. So you should never assume that two instances of Integer (or String, or any Object) will compare equal using ==, unless you are explicitly looking for reference equality.

Upvotes: 6

Matt Solnit
Matt Solnit

Reputation: 33572

You should use int instead of Integer, unless you need to handle null values.

There are indeed issues with comparing Integer objects. For example, the following will evaluate to false:

boolean test = (new Integer(1) == new Integer(1));
System.out.println(test); // "false"

These are just objects like any other. The == operator, when used with objects, only evaluates to true if they are the exact same Java object (as opposed to the equals() method, which can be overridden to compare the internals).

Upvotes: 3

Related Questions