Saturday, March 3, 2012

Java reference type primitives gotcha

Java has a gotcha on its reference type primitives, any reference type primitives that has a value between -128 to 127 are cached, in order to save memory. When you compare any number that fall on that range, don't be surprised that reference types with same values points to the same memory location

private static void firstTestRef() {                                   
 System.out.println("First Test Ref\n");                            
                                                                    
 Integer a = 126;                                                   
 Integer b = 127;                                                   
                                                                    
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 ++a;                                                               
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
}                                                                      

Output:
First Test Ref

Same reference b == a : false
Same value b.equals(a) : false

Same reference b == a : true
Same value b.equals(a) : true


See the output above? When you increment a, the runtime will check first if the value is in -127 to 128 range, if it is, it will find an existing object with same value, and reference that object instead


Now check the output of this one, values that are not in -128 to 127 range:

private static void secondTestRef() {                                  
 System.out.println("Second Test Ref\n");                       
                                                                    
 Integer a = 128;                                                   
 Integer b = 129;                                                   
 Integer c = a;                                                     
                                                                    
                                                                    
 System.out.printf("Same reference a == c : %b\n", a == c);         
 System.out.printf("Same value a.equals(c) : %b\n\n", a.equals(c)); 
                                                                    
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 ++a;                                                               
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 --a;                                                               
 System.out.printf("Same reference a == c : %b\n", a == c);         
 System.out.printf("Same value a.equals(c) : %b\n\n", a.equals(c)); 
}   


Output:

Second Test Ref

Same reference a == c : true
Same value a.equals(c) : true

Same reference b == a : false
Same value b.equals(a) : false

Same reference b == a : false
Same value b.equals(a) : true

Same reference a == c : false
Same value a.equals(c) : true

When you increment a, even it will have same value as b, their referenced memory location will not be the same. Even if you assign a its old value, a will be a new object already; so, even a has same value as c, it will not reference c

No comments:

Post a Comment