class java 常量池 java中常量池_java对象常量池

1.简介

特指运行时的常量池,存放在内存的方法区的中。一个JVM只有唯一的一个常量池,各线程共享该常量池;

保存了在编译期间就已经确定的数据。包括final常量值(局部常量、成员常量以及引用常量)和对象字面值;

在编译期间,每当给常量赋值时,它就会去检测常量池中是否存在该值。若存在,直接返回该值的地址给常量;若不存在该值,则会在常量池中创建该值,并把该值的地址返回给常量;

注意:常量池中不会存在相等的值。

2.存储值类型

final常量:一切经过final关键字修饰的变量均为常量,final常量在定义时必须赋初值,否则编译不通过;

对象字面量:直接把一常量赋值给对象。并不是在对堆空间中利用new来创建对象

基本类型包装类的对象字面量:

java中基本类型的包装类大都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。 两种浮点数类型的包装类Float,Double并没有实现常量池技术。

Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println("i1=i2 " + (i1 == i2));
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
System.out.println("i1=i4 " + (i1 == i4));
System.out.println("i4=i5 " + (i4 == i5));
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
System.out.println("40=i5+i6 " + (40 == i5 + i6));
i1=i2 true
i1=i2+i3 true
i1=i4 false
i4=i5 false
i4=i5+i6 true
40=i5+i6 true

解释:语句i4 == i5 + i6,因为+这个操作符不适用于Integer对象,首先i5和i6进行自动拆箱操作,进行数值相加,即i4 == 40。然后Integer对象无法与数值进行直接比较,所以i4自动拆箱转为int值40,最终这条语句转为40 == 40进行数值比较。

String类型的对象字面量:

String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
System.out.println("string" == "str" + "ing");// true
//连接表达式 +,只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入常量池中。
System.out.println(str3 == str4);//false
//对于字符串变量的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,其属于在运行时创建的字符串,具有独立的内存地址,所以不引用自同一String对象
String str5 = "string";
System.out.println(str3 == str5);//true
补充:String.intern()方法强制将字符串放入常量池中
public static void main(String[] args) {
String s1 = new String("计算机");
String s2 = s1.intern();
String s3 = "计算机";
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s3 == s2? " + (s3 == s2));
}
s1 == s2? false
s3 == s2? true

解释:String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池。

注意事项:final常量必须在定义时就赋初值,但对象字面量可以先定义后赋值

优点:常量池是为了避免频繁的创建和销毁对象而影响系统性能,实现了常量池中的内容由对象共享。例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中

节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间

节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等