您的位置:首页 > 职场人生

Interger对象源码解析

2016-12-21 19:10 323 查看
今天研究了Interger的源码,看了源码后才知道根本,以前做过的关于interger的面试题都迎刃而解。

今天以面试题为引子

       Integer a5=128;

        Integer a6=128;

        Integer a7=127;

        Integer a8=127;

        Integer a9=new Integer(127);

      

        System.out.println(a5==a6);//false

        System.out.println(a7==a8);//true

        System.out.println(a9==a8);//false

        System.out.println(a9.equals(a8));在程序中运行 jdk1.7的环境下 是false,大家都知道 == 比对的地址的引用(不知道的话可以自行去搜索下,网上很多的例子)

通过上面可以得到 a8 和 a9的数值相等 但是所引用的地址不是一样的。为什么呢?

首先虚拟机在编译的过程中会把代码优化一遍,也就是说上面的代码可能不是我们想要的。先看一下编译之后的代码什么样子。

(class文件反编译之后的代码)

       Integer a5 = Integer.valueOf(128);

        Integer a6 = Integer.valueOf(128);

        Integer a7 = Integer.valueOf(127);

        Integer a8 = Integer.valueOf(127);

        Integer a9 = new Integer(127);

        System.out.println(a5 == a6);

        System.out.println(a7 == a8);

        System.out.println(a9 == a8);

        System.out.println(a9.equals(a8));

大家可以看到 编译器优化之后真正运行的代码是这样子的。=128 优化成了 Integer.valueOf(128).

然而  Integer.valueOf做了什么事情呢?怎么会 两个128相比较会是不同的对象 两个127 相比较就是相同的数据呢?

带着疑问翻开了jdk源码(大家可以用 intellij idea 直接查看源码)

public static Integer valueOf(int i) {

    assert IntegerCache.high >= 127;

    if (i >= IntegerCache.low && i <= IntegerCache.high)

        return IntegerCache.cache[i + (-IntegerCache.low)];

    return new Integer(i);

}

首先第一眼看过去这是个静态的方法,通过Interger对象可以直接调用。看里面的内容,第一次看的时候猜想了作者的意思,大约是判断传送过来的i的数据 是否在   IntegerCache.low  和 IntegerCache.high中间,如果在的话返回一个IntegerCache.cache[i + (-IntegerCache.low)]。如果不在的话 new 一个对象。接着顺藤摸瓜,看下上面这3个东西是什么。

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

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

        }

        high = h;

        cache = new Integer[(high - low) + 1];

        int j = low;

        for(int k = 0; k < cache.length; k++)

            cache[k] = new Integer(j++);

    }

    private IntegerCache() {}

}

研究了代码发现,IntegerCache 是一个静态的 私有的方法,里面有很多的静态对象,静态是什么?简单的可以认为全局变量,谁都可以用,被缓存的数据。low 是 -128  high 默认是127 也可以配置,上面的意思是在程序启动的时候,初始化一部分数据存在内存中,这些数据是什么呢?

for(int k = 0; k < cache.length; k++)

            cache[k] = new Integer(j++);

    }

大家可以看到 这里进行了一次for循环,里面有个new 关键字(new 就是在堆中分配一块内存),每次都创建一个对象,内  容是 low和high 中间的所有数据面也就是 (-128)到(127)中的数据,共255 Interger对象,新建了这些对象之后,吧他们的地址的引用存在了static final Integer cache[];  中,这是一个数据,而且是静态的存在了缓存中,且不可变。

好了明白这些数据之后 再回过头来看下上面的代码所表达的意思。

Integer.valueOf(i)中,判断传送过来的i 是否在 -128 和127 中间,如果在就返回return IntegerCache.cache[i + (-IntegerCache.low)];   不在就返回 一个new 对象。

所以当

Integer.valueOf(128)的时候 比 127大 ,每次都是new 一个新的对象,

Integer.valueOf(127)的时候  等于127,就从缓存中拿出127的地址,不用新建一个对象了。

所以

System.out.println(a5==a6);//false

System.out.println(a7==a8);//true

每次new 的都是一个新的对象,不管缓存中是否存在,所以   System.out.println(a9==a8);//false

这是我看interger源码中比较有感触的地方,有不到和错误之处请说出来大家一起进步。

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题 源码 interger