What happens to Integer between - 128-127?

. equals and of Integer==

This is a basic question. People who master some java may be able to say why. But a closer look will reveal why

An ordinary code

public class Demo {
    public static void main(String[] args) {
        Integer i1 = 100;
        Integer i2 = 100;
        System.out.println(i1 == i2);  //Output true
        i1 = 1000;
        i2 = 1000;
        System.out.println(i1 == i2);  //Output false

After JDK1.5, the compiler provides the function of automatic unpacking and boxing. Integer i = 100 is the compiler that helps us automatically boxing.

Look at the decompiled code

public class Demo {
   public static void main (String [] args){
   Integer i1 = Integer.valueOf(100); 
   Integer i2 = Integer.valueOf(100); 
   i1 = Integer.valueOf(1000); 
   i2 = Integer.valueOf(1000); 

This is the process of automatic packing. Next, let's look at what happened in valueOf and paste the source code directly

     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as 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.
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);

Let's look at the logic in the method. This method will judge whether the incoming int value is between the highest value and the lowest value of IntegerCache. If it is between, the Integer object will be obtained from the cache of IntegerCache, otherwise a new Integer object will be created.
Before that, there is a static code block

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 =
            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;

It can be seen from here that Integer makes an array between - 128 and 127
The elements in IntegerCache.cache are arranged from - 128 to 127 in the order of 0-256 of the array. Assuming that the I passed in is = - 128, the subscript is calculated through the addressing formula
i + (-IntegerCache.low) = -128 + (128) = 0

Think about the initial question

At this step, we can understand why when the value of Integer is [- 128, 127], using = = to judge two integers with equal values can get true, but beyond this range, using = = to judge two integers with equal values can get false? Because when the value is between [- 128, 127], the valueOf method will not create a new Integer object, but get it from the cache. In this way, the calculated subscripts of int with the same value are the same, and naturally the same Integer object will be obtained. If it exceeds this range, it will not be obtained from the cache. Each time, a new Integer object is new. The memory addresses of two different objects are different. If = = is used, it will naturally get false.

Static inner class IntegerCache

After understanding the principle of boxing, we might as well take a look at how the cache of IntegerCache is initialized.

The process of initializing the cache is as follows

Get the parameter java.lang.Integer.IntegerCache.high in the JVM and convert it to type int as the value of high

Calculate the difference between high and low and + 1 as the length of the cache array

Incrementing continuously from - 128, set an Integer object at each position of the cache array.

Tags: Java

Posted on Thu, 28 Oct 2021 08:06:34 -0400 by TomNomNom