Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java原生类型包装类初解析 #14

Open
aCoder2013 opened this issue Oct 10, 2017 · 0 comments
Open

Java原生类型包装类初解析 #14

aCoder2013 opened this issue Oct 10, 2017 · 0 comments
Labels

Comments

@aCoder2013
Copy link
Owner

aCoder2013 commented Oct 10, 2017

首先看一段代码

        Integer a = 126;
        Integer b  =126;
        Integer c = 129 ;
        Integer d = 129 ;
        System.out.println(a==b);
        System.out.println(c==d);

输出结果会是多少呢,相信每个人心中都会有自己的答案,倒不如直接运行一下看看:

true
false

现在就有了疑问,为什么两个输出的结果不一样呢,这里就设计到了Integer设计了,我们可以用javap命令反编译一下字节码,看看到底发生了什么:

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=5, args_size=1
         0: bipush        126
         2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: astore_1
         6: bipush        126
         8: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        11: astore_2
        12: sipush        129
        15: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        18: astore_3
        19: sipush        129
        22: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        25: astore        4
        27: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        30: aload_1
        31: aload_2
        32: if_acmpne     39
        35: iconst_1
        36: goto          40
        39: iconst_0
        40: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
        43: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        46: aload_3
        47: aload         4
        49: if_acmpne     56
        52: iconst_1
        53: goto          57
        56: iconst_0
        57: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
        60: return

从字节码中可以看出是调用了Integer类的静态方法valueOf(),因此我们再进去Integer的源码研究一下:

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

那么这里的IntegerCache类有什么秘密呢,我们也进去看一下源码,IntegerCache是Integer的一个私有内部类,构造器也是
私有的,保证了安全性,通过源码可以看出,low的值默认为-128,修饰符为static final,因此不可再更改其值,而high
的值可以通过设置参数-XX:AutoBoxCacheMax来设置,同时内部维护了一个static finalInteger数组.

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

可以看出如果大于IntegerCache.low并且小于IntegerCache.high的话,则直接返回缓存中的对象,
因此用==比较肯定是相等的,如果if的条件不成立的话,那么就会new一个新的Integer对象返回,
因此肯定是不相等的
对于Boolean则是内部维护了两个常量:

    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);

对于Short和Long其实和Integer的实现差不多,只不过缓存的范围写死在了代码里面:

 final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);

对于Double和Float来说,则是直接返回,不进行任何缓存的操作:

    public static Double valueOf(double d) {
        return new Double(d);
    }

Flag Counter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant