9

Someone postulated in some forum thread that many people and even experienced Java Developers wouldn't understand the following peace of Java Code.

Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1++ == i2++);
System.out.println(i1 == i2);

As a person with some interest in Java I gave it my thoughts and came to the following result.

System.out.println(i1++ == i2++);
// True, since we first check for equality and increment both variables afterwards.

System.out.println(i1 == i2);
// True again, since both variables are already incremented and have the value 128

Eclipse tells me otherwise. The first line is true and the second is false.

I really would appreciate an explanation.

Second question. Is this Java specific or does this example hold for example for the C based languages, too?

Aufwind
  • 25,310
  • 38
  • 109
  • 154

2 Answers2

14
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1++ == i2++); 
// here i1 and i2 are still 127 as you expected thus true
System.out.println(i1 == i2); 
// here i1 and i2 are 128 which are equal but not cached
    (caching range is -128 to 127), 

In case 2 if you use equals() it'd return true as == operator for integers only works for cached values. as 128 is out of cache range the values above 128 will not be cached, thus youhave to use equals() method to check if two integer instances above 127 are true

TEST:

Integer i1 = 126;
    Integer i2 = 126;
    System.out.println(i1++ == i2++);// true
    System.out.println(i1 == i2); //true



 Integer i1 = 126;
        Integer i2 = 126;
        System.out.println(i1++ == i2++);// true
        System.out.println(i1.equals(i2)); //true

  Integer i1 = 128;
        Integer i2 = 128;
        System.out.println(i1++ == i2++);// false
        System.out.println(i1==i2); //false

  Integer i1 = 128;
        Integer i2 = 128;
        System.out.println(i1++.equals(i2++));// true
        System.out.println(i1.equals(i2)); //true
PermGenError
  • 45,977
  • 8
  • 87
  • 106
  • 4
    As a note of caution, I believe the caching range is JVM implementation specific and not part of the JLS. Therefore, this behaviour isn't guaranteed to be consistent across JVMs. – Chris Knight Feb 25 '13 at 10:35
  • 1
    @ChrisKnight It's not implementation-specific, as it is in the specification. [Paragraph 5.1.7](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7) states: *"If the value p being boxed is [...] an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2."* – Mattias Buelens Feb 25 '13 at 10:39
  • 1
    @Mattias Buelens - We are both right. To clarify, -128 to 127 (inclusive) is guaranteed. However, JVM's may extend this cached range. Further text in your reference: "Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.". – Chris Knight Feb 25 '13 at 10:43
  • 1
    @MattiasBuelens Yes, meaning that all JVMs must cache -128/127, but a JVM might decide to also cache 128 for example. – assylias Feb 25 '13 at 10:43
  • @ChrisKnight Ah, I see what you mean now. Indeed, implementations may choose to extend the range. The specification also states: *"For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part."* In that sense, you're right about being cautious about this as you cannot rely on this extended range as a programmer. – Mattias Buelens Feb 25 '13 at 11:17
  • can the downvoter leave a comment please . – PermGenError Mar 05 '13 at 11:25
1

As explained this is due to Integer caching. For fun, you can run the program with the following JVM option:

-XX:AutoBoxCacheMax=128

and it will print true twice (option available on hostpot 7 - not necessarily on other JVMs).

Note that:

  • this is JVM specific
  • the modified behaviour is compliant with the JLS which says that all values between -128 and +127 must be cached but also says that other values may be cached.

Bottom line: the second print statement is undefined in Java and can print true or false depending on the JVM implementation and/or JVM options used.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Just ran it with that parameter - and still got False. – Aleks G Feb 25 '13 at 10:44
  • @AleksG It works with hotspot version 7u11. – assylias Feb 25 '13 at 10:45
  • With OpenJDK on 64-bit Linux it doesn't. – Aleks G Feb 25 '13 at 10:46
  • @AleksG As explained it is JVM specific. – assylias Feb 25 '13 at 10:47
  • See for example the comment in [this code](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/Integer.java#Integer.IntegerCache) around line 585. – assylias Feb 25 '13 at 10:48
  • Possibly starting with java 7, however, also look at [this chapter](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7) in the specifications, where it states that it's always -128 to 127. – Aleks G Feb 25 '13 at 10:50
  • @AleksG No it says that -128/127 *must* be cached - but it also says that other values *may* be cached. Just wanted to point out that the result of the second condition in the OP's code is undefined and depends on VMs / Options. – assylias Feb 25 '13 at 10:51