Skip to content

Integer 源码分析

Posted on:December 31, 2020 at 16:26:36 GMT+8

JDK1.8

概述

源码注释

Integer 类将基本类型 int 的值包装成一个对象。一个类型为 Integer 对象包含类型为 int 的单个域。

另外,这个类提供了许多将一个 int 转换为 StringString 转换为 int 的方法,还有其它的一些处理 int 时有用的常量和方法。

IntegerCache

Integer 类中有一个私有静态内部类—— IntegerCache

IntegerCache 的源码注释:

用于支持被 JLS 要求的值在 -128 到 127 (含) 的自动装箱对象辨识语义。

这个缓存在第一次使用时初始化。cache 的大小可以通过 -XX:AutoBoxCacheMax=<size> 来控制。在虚拟机初始化期间,java.lang.Integer.IntegerCache.high 属性可以被设置,存在 sun.misc.VM 类中私有的系统属性中。

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() {}
}
public static void main(String[] args) {
    Integer a = new Integer(127);
    Integer b = new Integer(127);
    int c = new Integer(127);
    int d = new Integer(127);
    int e = new Integer(128);
    int f = new Integer(128);
    Integer g = 128;
    Integer h = 128;
    Integer i = 127;
    Integer j = 127;
    Integer k = 1;
    Integer l = 2;
    Integer m = 3;
    Long n = 3L;
    System.out.println(a == b); // false
    System.out.println(a.equals(b)); // true
    System.out.println(c == d); // true
    System.out.println(e == f); // true
    System.out.println(g == h); // false
    System.out.println(i == j); // true
    System.out.println(m == (k + l)); // true
    System.out.println(m.equals(k + l)); // true
    System.out.println(n == (k + l)); // true
    System.out.println(n.equals(a + b)); // false
}
javap -c Test

输出:

Compiled from "Test.java"
public class stack.Test {
  public stack.Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: bipush        127
       6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
       9: astore_1
      10: new           #2                  // class java/lang/Integer
      13: dup
      14: bipush        127
      16: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      19: astore_2
      20: new           #2                  // class java/lang/Integer
      23: dup
      24: bipush        127
      26: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      29: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      32: istore_3
      33: new           #2                  // class java/lang/Integer
      36: dup
      37: bipush        127
      39: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      42: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      45: istore        4
      47: new           #2                  // class java/lang/Integer
      50: dup
      51: sipush        128
      54: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      57: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      60: istore        5
      62: new           #2                  // class java/lang/Integer
      65: dup
      66: sipush        128
      69: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V
      72: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      75: istore        6
      77: sipush        128
      80: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      83: astore        7
      85: sipush        128
      88: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      91: astore        8
      93: bipush        127
      95: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      98: astore        9
     100: bipush        127
     102: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     105: astore        10
     107: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     110: aload_1
     111: aload_2
     112: if_acmpne     119
     115: iconst_1
     116: goto          120
     119: iconst_0
     120: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     123: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     126: aload_1
     127: aload_2
     128: invokevirtual #8                  // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
     131: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     134: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     137: iload_3
     138: iload         4
     140: if_icmpne     147
     143: iconst_1
     144: goto          148
     147: iconst_0
     148: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     151: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     154: iload         5
     156: iload         6
     158: if_icmpne     165
     161: iconst_1
     162: goto          166
     165: iconst_0
     166: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     169: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     172: aload         7
     174: aload         8
     176: if_acmpne     183
     179: iconst_1
     180: goto          184
     183: iconst_0
     184: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     187: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
     190: aload         9
     192: aload         10
     194: if_acmpne     201
     197: iconst_1
     198: goto          202
     201: iconst_0
     202: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
     205: return
}

可以看到后面 4 个都调用了 Integer#valueOf 方法。

包装类的 “==” 在不遇到算术运算的时候不会自动拆箱,包装类的 equals 方法不处理数据转型。

valueOf

返回一个代表指定 int 值的 Integer 实例。如果不需要一个新的 Integer 实例,通常应该优先使用本方法,而不是使用构造函数 Integer(int),因为本方法通过缓存频繁请求的值,可能会产生更好的空间和时间性能。本方法将始终缓存 -128 到 127 (含)范围内的值,并可能缓存这个范围之外的其他值。

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