一、Java中对象的比较
我们都知道,Java的对象名其实是一个引用,指向堆中的某个位置,如果两个对象指向同一个位置,那么用==号比较两个对象,得到的结果就是true。而如果两个对象指向内存中不同位置,那么用==号比较的话,会得到false,这个时候要去重写对象的equals方法来进行比较。
二、Integer中的==比较
如上图所示,写了一段代码,来比较a和b,c和d。大家猜一下答案应该是什么呢?
是不是很奇怪?
通过上述代码,我们可以得出,a和b其实指向的是同一个对象,而c和d则指向的是不同的对象
让我们去看看这个类的字节码。在IDEA左侧导航栏中单击这个类:
然后点击view,找到show bytecode,可以查看字节码:
看不懂没关系,我们注意到,当执行Integer a = 100,这条语句的时候,调用的是Integer.valueOf方法。那么我们去追踪一下这个方法。
按住ctrl(mac上是command),左键单击Integer,即可进入Integer类。
我们搜索一下这个类的valueOf方法,代码如下:
可以看到,当输入处于IntegerCache.low 和 IntegerCache.high之间的时候,返回的是IntegerCache中的cache数组的值。而大于那个范围,才是另外去new一个Integer。
让我们继续追踪,什么是IntegerCache?
它是Integer中的一个静态内部类,里边有一个Integer数组,用来存储-128到127的值。
所以答案解开了,因为a和b都是指向IntegerCache中的值为100的那个Integer对象,所以进行==比较的结果返回true。而c和d大于127,所以每次都会重新new一个Integer对象,所以c和d指向的不是内存中的同一个地方,因此==比较的时候会返回false。
三、为什么引入IntegerCache
IntegerCache是JDK1.5中被引入的,因为这些小数字在生活中被频繁使用,如果每次使用都去重新new的话,会带来性能开销。在第一次使用Integer的时候,IntegerCache中的cache数组就被初始化好。每次用等号给Integer赋值的时候,都会检查是否在-128和127之间。
注意:只有用=给Integer赋值,才会自动装箱,隐式去调用valueOf。如果直接new的话,IntegerCache并不起作用:
上边的代码输出为false。
四、其他包装类
Byte,Short,Long,Character都有类似于Integer的缓存,其中除了Character是0~127之外,其他的都是-128~127。大家感兴趣的可以去看看源码。另外Integer的Cache范围可以通过JVM启动参数来设置,而其他的不行。
一般来说,如果没有什么特别用途,这类问题,可能永远都不会关注,但有面试官喜欢问,以检验你的基本功咋样。所以,就多积累吧,涨点见识也不错嘛~
看完了,记得关注、分享、点个赞啥的^_^
閱讀更多 3T教育編程猿 的文章