I just saw code similar to this:
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.o
My guess is that Java keeps a cache of small integers that are already 'boxed' because they are so very common and it saves a heck of a lot of time to re-use an existing object than to create a new one.
Yes, there is a strange autoboxing rule that kicks in when the values are in a certain range. When you assign a constant to an Object variable, nothing in the language definition says a new object must be created. It may reuse an existing object from cache.
In fact, the JVM will usually store a cache of small Integers for this purpose, as well as values such as Boolean.TRUE and Boolean.FALSE.
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000; //1
System.out.println(a == b);
Integer c = 100, d = 100; //2
System.out.println(c == d);
}
}
Output:
false
true
Yep the first output is produced for comparing reference; 'a' and 'b' - these are two different reference. In point 1, actually two references are created which is similar as -
Integer a = new Integer(1000);
Integer b = new Integer(1000);
The second output is produced because the JVM
tries to save memory, when the Integer
falls in a range (from -128 to 127). At point 2 no new reference of type Integer is created for 'd'. Instead of creating a new object for the Integer type reference variable 'd', it only assigned with previously created object referenced by 'c'. All of these are done by JVM
.
These memory saving rules are not only for Integer. for memory saving purpose, two instances of the following wrapper objects (while created through boxing), will always be == where their primitive values are the same -
\u007f
(7f is 127 in decimal) Class Integer
contains cache of values between -128 and 127, as it required by JLS 5.1.7. Boxing Conversion. So when you use the ==
to check the equality of two Integer
s in this range, you get the same cached value, and if you compare two Integer
s out of this range, you get two diferent values.
You can increase the cache upper bound by changing the JVM parameters:
-XX:AutoBoxCacheMax=<cache_max_value>
or
-Djava.lang.Integer.IntegerCache.high=<cache_max_value>
See inner IntegerCache class:
/**
* Cache to support the object identity semantics of autoboxing for values
* between -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
In Java the boxing works in the range between -128 and 127 for an Integer. When you are using numbers in this range you can compare it with the == operator. For Integer objects outside the range you have to use equals.
Integer Cache is a feature that was introduced in Java Version 5 basically for :
Integer number1 = 127;
Integer number2 = 127;
System.out.println("number1 == number2" + (number1 == number2);
OUTPUT: True
Integer number1 = 128;
Integer number2 = 128;
System.out.println("number1 == number2" + (number1 == number2);
OUTPUT: False
HOW?
Actually when we assign value to an Integer object, it does auto promotion behind the hood.
Integer object = 100;
is actually calling Integer.valueOf() function
Integer object = Integer.valueOf(100);
Nitty-gritty details of valueOf(int)
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Description:
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
When a value within range of -128 to 127 is required it returns a constant memory location every time. However, when we need a value thats greater than 127
return new Integer(i);
returns a new reference every time we initiate an object.
==
operators in Java compares two memory references and not values.
Object1
located at say 1000 and contains value 6.
Object2
located at say 1020 and contains value 6.
Object1 == Object2
is False
as they have different memory locations though contains same values.