常量缓存池浅析
来源:互联网 发布:义乌美工学徒招聘 编辑:程序博客网 时间:2024/06/15 22:33
我们先看一段代码,很简单对不对
public class Demo { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); Integer i3 = 1000; Integer i4 = 1000; System.out.println(i3 == i4); }}
执行一下:
和大多数人心里想的不一样吧,好多人还在纠结,到底全是true还是全是false。
然而一个是true,一个是false,这是为什么呢?
首先我们找到.class文件来反编译一下,根据Java编译机制, .java文件在编译后会生成 .clas文件给JVM加载执行
public class Demo { public static void main(String[] args) { Integer i1 = Integer.valueOf(100); Integer i2 = Integer.valueOf(100); System.out.println(i1 == i2);
Integer i3 = Integer.valueOf(1000); Integer i4 = Integer.valueOf(1000); System.out.println(i3 == i4); }
}
诶,发现编译器在编译我们的代码时,在声明的变量上加了valueOf方法,那进一步来看一下valueOf方法的实现
public static IntegervalueOf(inti) {
if (i >= IntegerCache.low &&i <= IntegerCache.high) 看一下是否在缓存的数组里,如果在,直接取
return IntegerCache.cache[i + (-IntegerCache.low)]; 数组里相应的对象返回
return new Integer(i); 不在缓存的数组里,直接new一个对象返回
}
我们发现,Integer的作者在写这个类时,为避免重复创建对象,对Integer值做了缓存,如果这个值在缓存范围内,直接返回缓存好的对象,否则new一个新的对象返回,那究竟这个缓存到底缓存了什么呢?看一下IntegerCsche这个类:
privatestaticclassIntegerCache {
staticfinalintlow = -128;
staticfinalinthigh;
staticfinal Integercache[];
static {
// high value may be configured by property
/*
* 检查虚拟机里有没有相应的配置,如果有,取该值;如果没有,取默认的127
*/
inth = 127;
StringintegerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue !=null) {
try {
inti =parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}catch( NumberFormatExceptionnfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high =h;
/*
* 创建缓存数组,并给数组初始化值(缓存值)
*/
cache =new Integer[(high -low) + 1];
intj =low;
for(intk = 0; k < cache.length;k++)
cache[k] =new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assertIntegerCache.high >= 127;
}
private IntegerCache() {}
}
这是一个内部静态类,该类只能在Integer这个类的内部访问,这个类在初始化的时候,会去加载JVM的配置,如果有值,就用配置的值初始化缓存数组,否则就缓存-128到127之间的值。
再来看看之前的代码:
![](file:///C:/Users/46642/AppData/Local/Temp/enhtmlclip/Image(1).png)
结论:
我们在比较两个Integer对象时,无论是怎么声明的,都一定要使用equals去比较,不能用==。
引申:
8种基本类型的包装类和对象池
java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。以下是一些对应的测试代码:
publicclassDemo {
publicstaticvoidmain(String[]args) {
// 5种整形的包装类Byte,Short,Integer,Long,Character的对象,
// 在值小于127时可以使用常量池
Short s1= 127;
Shorts2= 127;
System.out.println(s1==s2);// 输出true
// 值大于127时,不会从常量池中取对象
Shorts3= 128;
Shorts4= 128;
System.out.println(s3==s4);// 输出false
// Character
Characterc1= 127;
Characterc2= 127;
System.out.println(c1==c2);// 输出true
// 值大于127时,不会从常量池中取对象
Characterc3= 128;
Characterc4= 128;
System.out.println(c3==c4);// 输出false
// Boolean类也实现了常量池技术
Booleanbool1=true;
Booleanbool2=true;
System.out.println(bool1==bool2);// 输出true
// 浮点类型的包装类没有实现常量池技术
Doubled1= 1.0;
Doubled2= 1.0;
System.out.println(d1==d2);// 输出false
}
}
看一下Console
![](file:///C:/Users/46642/AppData/Local/Temp/enhtmlclip/Image(2).png)
阅读全文
0 0
- 常量缓存池浅析
- 常量池与缓存类
- java堆栈,常量池的浅析
- Java笔记之常量池浅析
- 包装类缓存池浅析
- 常量池和包装类缓存
- Java常量池详解之Integer缓存
- 浅析字符常量区
- DirectX11 常量缓存
- DirectX11 HLSL常量缓存
- IE缓存机制浅析
- ibatis缓存浅析
- ibatis缓存浅析
- ibatis缓存浅析
- ibatis缓存浅析
- Browser缓存机制浅析
- 浅析hibernate缓存机制
- iOS 缓存机制浅析
- web字体优化
- 机器学习ing
- Qt5.8 linux程序打包发布
- 集群基础------(heartbeat心跳组件)
- 【剑指Offer】面试题46:求1+2+3+...+n
- 常量缓存池浅析
- 程序员面试系列——插入排序
- 互联网电视技术方案分析与比较
- Servlet--ServletContext(三)获取web.xml配置参数
- 解决设置相同高度情况下<input>和<button>不同高
- hdu 2014 青年歌手大奖赛_评委会打分
- 求s=a+aa+aaa+aaaa+aa...a的值 oj7
- 使用unity进行零件装配
- (XML&Java)TextView居中&TextView中的文字居中