大家好,欢迎来到IT知识分享网。
关于Integer ,作为int 包装类,新手经常会犯的错误是,比较两个Integer 用 ==,作为有经验的开发我们知道,包装类、String 都应用用equals方法进行判断。
在实际项目中,我们经常会有枚举值定义成Integer类型,有相当部分同学不注意,使用== 进行了比较,但是似乎又也没怎么出现Bug。这就不得不提起 Integer内部类 IntegerCache,它缓存了[-128,127] 的对象,这里使用了享元模式,避免了对象的重复创建。
因为枚举值数量通常比较小,在[-128,127] 之间,代码中也没有谁变态到 new Integer(value),所以,许多场景使用的是 IntegerCache 缓存的对象,所以== 没出现了问题。但不能说这么用没有错,程序员要严谨,以防后续用到数值超过缓存的范围,且不排除谁用new Integer 创建对象。
虽然IntegerCache 不对外暴露,但是Java反射,可是神通广大,如果用反射把一些缓存的值改掉,就会产生“有意思的”结果。下面代码大家觉得输出什么
Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField("value"); valueField.setAccessible(true); valueField.set(one,128); System.out.println((Integer)1 == 128);
输出true
其实这个涉及知识点不少,涉及Java 自动拆箱、Integer缓存
左边包装类 右边基本类型,会把左边拆卸为基本类型,由于它的value 已经被改为128了,所以输出true .
但是上述代码稍微修改下, 改为 Integer(1) == (Integer)128
Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField("value"); valueField.setAccessible(true); valueField.set(one,128); System.out.println((Integer)1 == (Integer)128);
结果就为false。
因为上面代码两个Integer 类型,比较是不是同一个对象,显然128不在缓存中,
如果把128 改为缓存范围内一个数呢,如下,结果也会为false。
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField("value"); valueField.setAccessible(true); valueField.set(one,3); System.out.println((Integer)1 == (Integer)3); }
学C++的,估计第一次接触这个要吐血了,既然说了顺便复习下Integer 类型值默认null ,int 默认值0。这个IntgerCache 确实饶了点。
同样的Long 也有类似的Cache,值得一提的是redis 中有类似的缓存,只是范围不一样,编程复杂度与空间开销方面,如果是我会选择简单,期待jdk某个版本会把它干掉。
讲完,后面持续输出
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/92896.html