Why does the behavior of the Integer constant pool change at 127?
No, the constant pool for numbers doesn't work the same way as for strings. For strings, only compile-time constants are interned - whereas for the wrapper types for integer types, any boxing operation will always use the pool if it's applicable for that value. So for example:
int x = 10;
int y = x + 1;
Integer z = y; // Not a compile-time constant!
Integer constant = 11;
System.out.println(z == constant); // true; reference comparison
The JLS guarantees a small range of pooled values, but implementations can use a wider range if they wish.
Note that although it's not guaranteed, every implementation I've looked at uses Integer.valueOf
to perform boxing operations - so you can get the same effect without the language's help:
Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
System.out.println(x == y); // true
From section 5.1.7 of the JLS:
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or 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.
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. 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.
Java Integer pool. Why?
It's called the Flyweight pattern and is used to minimize memory usage.
Those numbers are very likely to be used repeatedly, and autobox types like Integer
are immutable (note this is done not just for Integer
). Caching them makes it so there aren't lots of instances and reduces GC (Garbage Collection) work as well.
The JLS covers this in 5.1.7. Boxing Conversion specifically by saying:
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or 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.
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. 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.
Comparison of int to Integer not working after adding to Linkedlist
Do it as follows:
System.out.println(i.equals(ll.peek()));
Remember, ==
compares the references, not the content.
Check Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java? to understand why it returned true
for a number less than 128
.
Why Integers act as interns only for the values less than 128 (default) in java
Technically the values are pre-cached when the class is loaded. It is not like String.intern() where a value you created can be returned.
Also the maximum might not be 127, it can be higher if you set it so or use options like -XX:+AggressiveOpts
The default range is likely to be chosen just to be consistent with Byte. Note: the cached values are
Boolean: both values
Byte: all
Character: 0 to 127
Short: -128 to 127
Integer: -128 to 127
Long: -128 to 127
Float and Double: none
BigInteger: -16 to 16 (in HotSpot Java 7)
BigDecimal: 0 to 10 (if you use valueOf(long)) and
0 to 0.000000000000000 (if you use valueOf(long, int)) (in HotSpot Java 7)
The reason it is done is to improve performance and reduce GC pressure.
Creating garbage can fill your cache with garbage, slowing down all your code, it also takes work to create objects and to clean them up. The less work you do the faster and more consistent your program will be.
Here is a good article of the difference it makes http://www.javaspecialists.eu/archive/Issue191.html
Integer and Double difference
You are comparing Integer (capital I) objects by reference, which is not the "proper" way to compare objects in java.
References to some integers are cached in order to optimize for performance. This is why comparing certain Integer (capital I) objects by reference seems to work in a few cases in Java.
This is NOT a behavior that the Java developer is expected to rely on or make use of, as it is unreliable, may change, and makes code more difficult to understand.
Long and Double comparison (==) behaves differently
Long v1 = 1L;
Long v2 = 1L;
Double d1 = 1.0;
Double d2 = 1.0;
You are creating two references to objects here, and instantiating two objects with autoboxing behaviour of Java.
Java re-uses the same Long object instance from a pool for v1 and v2, The Doubles do not use a pool for remembering values, as can be read in this informative blog entry https://gerardnico.com/code/type/autoboxing
Here are some rules as with Java 5 :
autoboxing to Boolean and Byte always returns an object from the pool
autoboxing to Char, Short, Integer and Long returns an object from the
pool when the autoboxed value is between -128 and 127 (inclusive)
autoboxing of Float and Double does not use the pool and always
returns a new object
Your code becomes then with autoboxing(some pool is a visualisation of the pool java uses to cache certain values):
class SomePoolJavaUses {
static Long _l1 = new Long(1L);
static Long _l2 = new Long(2L);
static Long _l3 = new Long(3L);
...
}
Long v1 = SomePoolJavaUses._l1;
Long v2 = SomePoolJavaUses._l1;
Double d1 = new Double(1.0);
Double d2 = new Double(1.0);
This means that d1 and d2 are not equal instances, so they are not equal in ==
This means that v1 and v2 are equal instance, so they are equal in ==
the v1.equals
returns true, because there is being looked at the actual value there instead of a quick check if the memory addresses are the same.
Java use same reference for some objects but sometimes it creates 2 instances
Integer uses Integer cache to store the values from -128 to +127. If == operator is used to check for any values between -128 to 127 then it returns true. for other than these values it returns false
If you have tried like this,
Integer i1 = 1000;
Integer i2 = 1000;
Integer i3 = new Integer(10);
Integer i4 = new Integer(10);
System.out.println(i1 == i2);
System.out.println(i3 == i4);
Output:
false
false
Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
When you compile a number literal in Java and assign it to a Integer (capital I
) the compiler emits:
Integer b2 =Integer.valueOf(127)
This line of code is also generated when you use autoboxing.
valueOf
is implemented such that certain numbers are "pooled", and it returns the same instance for values smaller than 128.
From the java 1.6 source code, line 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
The value of high
can be configured to another value, with the system property.
-Djava.lang.Integer.IntegerCache.high=999
If you run your program with that system property, it will output true!
The obvious conclusion: never rely on two references being identical, always compare them with .equals()
method.
So b2.equals(b3)
will print true for all logically equal values of b2,b3.
Note that Integer
cache is not there for performance reasons, but rather to conform to the JLS, section 5.1.7; object identity must be given for values -128 to 127 inclusive.
Integer#valueOf(int) also documents this behavior:
this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
Related Topics
How to Bundle a Native Library and a Jni Library Inside a Jar
Convert Float to String and String to Float in Java
Understanding the Workings of Equals and Hashcode in a Hashmap
How to Use a Wildcard in the Classpath to Add Multiple Jars
How to Convert Currenttimemillis to a Date in Java
Casting Object Array to Integer Array Error
How to Use Jaroutputstream to Create a Jar File
Gson Serialize a List of Polymorphic Objects
Does the Jvm Prevent Tail Call Optimizations
How to Retrieve Element Value of Xml Using Java
How to Create an .Exe for a Java Program
Java:If a Extends B and B Extends Object, Is That Multiple Inheritance
Using Mockito to Test Abstract Classes
Is It Good Practice to Use Java.Lang.String.Intern()
When Do Java Generics Require <? Extends T> Instead of <T> and Is There Any Downside of Switching
Http Basic Authentication in Java Using Httpclient
What Is the Equivalent Lambda Expression for System.Out::Println