Java常量池技术
- 介绍
当需要一个对象时,从池中去获取(如果池中没有,就创建一个并放入池中),当下次需要相同变量的时候,不用重新创建,从而节省空间。
- Class文件中的常量池
在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量和符号引用。
- 字面量:如文本字符串,声明为final的常量值
- 符号引用: 属于编译方面的原理,如类和接口的全限定名;字段名称和描述符;方法名称和描述符
- 方法区中的运行时常量池
- CLass文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
- 具备动态性,还包括动态运行时的常量,如String类的intern()
- 使用场景
- 基本数据类型
- Byte,Short,Integer,Long,Character,Boolean默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象
- 两种浮点数类型的包装类Float,Double并没有实现常量池技术。
- Integer面试题
- 拆箱装箱
装箱就是自动将基本数据类型转换为包装器类型;如 Integer i = 10; Integer.valueOf(int)
拆箱就是自动将包装器类型转换为基本数据类型。int n = i; Integer.intValue()
[-128,127]范围内的,
public static void main(String[] args) {
Integer i1 = new Integer(1200);
Integer i2 = new Integer(1200);//只要堆区参与比较,则始终不相等
Integer i3 = 1200;
Integer i4 = 1200;//栈区的和非堆区的比较会自动拆箱
int i5 = 1200;
int i6 = 1200;
System.out.println("堆空间-堆空间:"+(i1 == i2));//
System.out.println("栈空间-栈空间:"+(i3 == i4));//
System.out.println("常量池-常量池:"+(i5 == i6));//
System.out.println("堆空间-栈空间:"+(i1 == i3));//
System.out.println("堆空间-常量池:"+(i1 == i5));
System.out.println("栈空间-常量池:"+(i3 == i5));
}
- == 比较
堆区和常量池比较永远相等,栈区和常量池比较永远相等
堆区和堆区比较永远不等,栈区在范围内相等范围外不等
A:Integer i1 = new Integer(21) 堆空间 | B:Integer i3 = 21 栈空间 | c:int i5 = 21 常量池 | ||||
范围内 | AA : false | BB :true | CC : true | AB : false | AC : true | BC : true |
范围外 | AA : false | BB :false | CC : true | AB : false | AC : true | BC : true |
- 代码:
Integer i1 = new Integer(1200);
Integer i2 = new Integer(1200);//只要堆区参与比较,则始终不相等
Integer i3 = 1200;
Integer i4 = 1200;//栈区的和非堆区的比较会自动拆箱
int i5 = 1200;
int i6 = 1200;
System.out.println("堆空间-堆空间:"+(i1 == i2));//
System.out.println("栈空间-栈空间:"+(i3 == i4));//
System.out.println("常量池-常量池:"+(i5 == i6));//
System.out.println("堆空间-栈空间:"+(i1 == i3));//
System.out.println("堆空间-常量池:"+(i1 == i5));
System.out.println("栈空间-常量池:"+(i3 == i5));
-
- String的面试题
- 特点
S.intern() 返回常量池中的原值
String是不可变的
- ==比较
![](https://i-blog.csdnimg.cn/blog_migrate/0f96db915c4dfb8f5b95f8c08f841e44.png)