2

Possible Duplicate:
Integer wrapper class and == operator - where is behavior specified?

I known Java integer use cache in -127~128. If

Integer i = 1;
Integer j = 1;

Integer m = 128;
Integer n = 128;

i == j // true
m == n // false

But I met a strange phenomenon.First,look at following snippet.

List<CustomerNotice> customerNotice = findByExample(example); // use Hibernate findByExample method

for(CustomerNotice n : customerNotice){
if(n.getConfirmStatus() == NoticeConfirmStatus.UNCONFIRMED.getValue()){
    // do sth
}
}
public enum NoticeConfirmStatus{
UNCONFIRMED(1), //
CONFIRMED(2), //
FAILED_TO_CONFIRM(3); //


private final Integer value;

private NoticeConfirmStatus(Integer  value) {

    this.value = value;
}

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

public class CustomerNotice {

@Column(name = "CONFIRM_STATUS")
private Integer confirmStatus;

public Integer getConfirmStatus() {
    return this.confirmStatus;
}
public void setConfirmStatus(Integer confirmStatus) {
    this.confirmStatus = confirmStatus;
}
}

Although the if expression is not recommended, I think it will be return true,because n.getConfirmStatus()==1, but the result is false.I'm very confusing.

In addition, theList<CustomerNotice> customerNotice acquired by Hibernate findByExample method. Is there some Autoboxing or new operation when retrieve the resultset?

Thank you.

Community
  • 1
  • 1
Argun
  • 415
  • 5
  • 20
  • Integer cache is -128 to 128 _by default_. The system property `java.lang.Integer.IntegerCache.high` can change the end number of that cache to something else (see [this](http://stackoverflow.com/questions/3934291/extending-java-integer-cahce)). Don't rely on the integer cache existing at all. – prunge Dec 15 '11 at 03:50
  • 2
    The default range is `-128` to `127` not 128. – Peter Lawrey Dec 15 '11 at 08:55

2 Answers2

3

SHORT: (answers question)

If you want to compare Integers as the objects, you should use .equals:

i.equals(j);
m.equals(n);

With this, they should both return true. But if you really want to use ==, you need to get the primitive int value:

i.intValue() == j.intValue();
m.intValue() == j.intValue();

LONG: (explains answer)

The basis of this is that Objects are always stored separately in memory (except for some special cases like m=n), and to be compared properly, they need to be broken down into primitive types that can be compared successfully using ==.

Every Object has a .equals() method, which is inherited from Object as its superclass. However, it must be overridden to do a proper comparison. Integer overrides this method to compare to Integer objects successfully, while using == checks to see if both objects point to the same space in memory, and because two instances of an Object cannot point to the same space in memory, this will always return false.

However, as your code points out, there are some special cases that work, like these:

  1. Your code uses a Integer i = 1, which is considered a "standard instance" and is able to be compared using ==.
  2. If you set one Object equal to another using =, Java tells both objects to point to the same location in memory, which means that == will return true.

There are many others, but those are the two that come to mind and seem relevant.

Jon Egeland
  • 12,470
  • 8
  • 47
  • 62
  • Thanks! Knowledge review. Compare contents of variable using **equals()**,reference using **==** – Argun Dec 15 '11 at 06:00
2

You'll drive yourself crazy and waste a lot of time trying to figure out specific cases where this works or does not work. It depends on the implementation of code which isn't always visible to you.

The bottom line: never, ever, use == to compare Integer instances, period. As you have seen, it works sometimes, under some circumstances, and fails miserably the rest of the time. If you have a method that returns an Integer, then assign the value to an int, and then you can use == to compare that int to another int.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • I'm sorry.Description of intention is not clearly. – Argun Dec 15 '11 at 05:06
  • The point is **if(n.getConfirmStatus() == NoticeConfirmStatus.UNCONFIRMED.getValue())** and hibernate how to setConfirmStatus().Because the expression return false,so i think the setter method like this operation. `n.setConfirmStatus(new Integer(1))`,and not `n.setConfirmStatus(Integer.valueOf(1))`. But i didn't how to prove my assertion. Do you understand my meanings? Thanks! – Argun Dec 15 '11 at 05:52
  • You're saying that you think Hibernate doesn't use `Integer.valueOf()`. I wouldn't necessarily expect it to. It *might* have special cases for primitive wrappers, or it might not. You experiment does seem to show that it does not; I don't find that terribly surprising. – Ernest Friedman-Hill Dec 15 '11 at 11:57