java.lang.Integer source code analysis

Integer

The source code of this article is based on JDK8

Integer is also a tool class and packaging class that we often use. This article is mainly used to record study notes, mainly from the perspective of source code.

public final class Integer extends Number implements Comparable<Integer> {
    // 2147483647
    public static final int   MIN_VALUE = 0x80000000;
    // -2147483648
    public static final int   MAX_VALUE = 0x7fffffff;

    // 获取基本类型int类型是class
    public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
}

Description: Integer.TYPE == int.class // true

  • Inherit the Number class

There are only constructors and a few abstract methods in the Number class:
write picture description here

Construction method

public Integer(int value) {
    this.value = value;
}
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

Autoboxing and Autounboxing

After JDK1.5, java provides the functions of automatic boxing and automatic unboxing. Let's analyze the boxing of Integer from the perspective of source code:

package com.quancheng;
public class ClassTest {
    public static void main(String[] args) throws InterruptedException {
        Integer num = 10;
    }
}

Looking at the bytecode through javap -v ClassTest.class, we can see that autoboxing is actually what the JVM compiler does for us, calling the Integer.valueOf() method

  public static void main(java.lang.String[]) throws java.lang.InterruptedException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: bipush        10
         2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: astore_1
         6: return

It can be seen from the analysis here that Integer a = 100 is actually equivalent to Integer a = Integer.valueOf(100); but this work is done for us by the JVM;

Automatic unboxing:

public static void main(String[] args) throws InterruptedException {
    int num = new Integer(11);
}

The corresponding bytecode instruction:

public static void main(java.lang.String[]) throws java.lang.InterruptedException;
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=3, locals=2, args_size=1
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: bipush        11
       6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
       9: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      12: istore_1
      13: return

Through analysis, it can be found that the automatic unboxing is actually the conversion completed by the compiler calling the Integer.intValue() method

focus method

  • valueOf method

    public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
    }

    IntegerCache is a static inner class, mainly used to cache the wrapper class of numbers between low and high

    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() {}
    }

    It can be seen from the above source code that IntegerCache has three static files modified by final plus a static block and a private constructor; a very simple and common class, the cached wrapper class is between low - high, low The value has been hard-coded -128, and the value of high is determined by your virtual machine sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"), since it is a parameter, it means that you can dynamically Settings, specifically how to set up Baidu. Then in the loop, the boxed method cache[] of the numbers between low and high is stored in the array of type Integer. This completes the cache

In daily coding, we need to pay attention to the problem of Integer cache

Integer a = 100;
Integer b = 100;
Integer f = Integer.valueOf(100);

Integer c = 200;
Integer d = 200;

System.out.println(a == b);//true
System.err.println(a == f); // true
System.out.println(c == d);//false
  • The method stringSize(int x)
    is very interesting. I think you can look at this method alone. The main function is to judge the number of digits of a number, but it is used very cleverly.
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

// Requires positive x
static int stringSize(int x) {
    for (int i=0; ; i++)
        if (x <= sizeTable[i])
            return i+1;
}
  • equals(Object obj)

It should be noted that Integer also rewrites equals(Object obj), so if the value types compared are Integer, equals() and == have the same effect

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}
我们可以写个例子测试下:
Integer num = new Integer(999);
System.err.println(num ==999);

public static void main(java.lang.String[]) throws java.lang.InterruptedException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: new           #2                  // class java/lang/Integer
         3: dup
         4: sipush        999
         7: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
        10: astore_1
        11: getstatic     #4                  // Field java/lang/System.err:Ljava/io/PrintStream;
        14: aload_1
        15: invokevirtual #5                  // Method java/lang/Integer.intValue:()I
        18: sipush        999
        21: if_icmpne     28
        24: iconst_1
        25: goto          29
        28: iconst_0
        29: invokevirtual #6                  // Method java/io/PrintStream.println:(Z)V
        32: return

It can be seen that it is actually unboxing and then comparing the values

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325674113&siteId=291194637