在JAVA SE的学习中遇到关于常量池的一些总结
在学习JAVA的时候,特别是学到JVM的时候,常量池的存在感觉有些颠覆认知,所以总结一下自己的看法,有不对的地方,希望大佬指正
常量池的定义
顾名思义,常量池即存放常量的内存空间,常量分为两种:
1 基本数据类型如“11”,“a”,
2 final修饰并赋值后的量
常量池的位置
JDK1.7以前,常量池位于方法区
JDK以后,常量池移入堆
常量池的作用
1 节省内存空间:所有常量池中相同的常量具有同样的内存地址
2 加快运行速率
关于常量池容易出错的地方
public static void main(String[] args) {
String str ="a";
String str2="a";
String str3="b";
String str4=new String("b");
String str5="ab";
String str6="a"+"b";
String str7="ab".intern();
System.out.println(str==str2);
System.out.println(str3==str4);
System.out.println("ab"==str+str3);
System.out.println(str5=="a"+"b");
System.out.println(str5==str+str3);
System.out.println(str5==str6);
System.out.println(str5==str7);
}
以上代码运行的结果为
true
false
false
true
false=
true
true
我们来分析一下结果出现的原因
(1)str1=str2,但str3!=str4,这是因为当我们定义String str="a"的时候,其实创建了两个对象,一个在常量池中,一个在堆中,当第二次再用String str2="a"创建对象时,这个str2引用的就是常量池的地址,所以和str是相等的,而str4因为使用了new方法,即重新在堆中创建了对象,所以并不使用常量池的地址,因而与str3不相等
(2)str5==“a”+"b"正确但"ab"str+str3却错误,是字符串的拼接只能发生在编译期间,str5是已经定义在常量池中的常量,而"a"+"b"的拼接在编译器已经进行完成,所以编译完后等式为str5=“ab”。但str和str3在编译的时候都是未知量,无法被编译,这个等式最后输出的是false
(3)str5str+str3显然不成立,因为str与str3都不是常量,无法拼接,所以在相加之后地址也不是指向常量池
(4)str5=str6因为字符拼接
(5)intern()方法返回的就是字符的常量池地址
关于包装类进入常量池
除了Double与Float两个包装类其他六个都实现了部分数据进入常量池,最常用的Integer,它在-128~127这一段中的数据是进入常量池的,而剩下几种在127以下也是进入常量池的,而ASCII表的上限正好是127
public static void main(String[] args) {
Integer a =127;
Integer b =127;
Integer c =new Integer(127);
Integer d =128;
Integer e =128;
Integer f =new Integer(128);
System.out.println(a==b);
System.out.println(a==c);
System.out.println(d==e);
System.out.println(d==f);
}
上述代码运行的结果是
true
false
false
false