常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。
上面是百度常量池的解释。一开始不太懂,后来又去各大IT网站去搜索了一番。通过一些代码,稍微理解了点,如有不对,请不吝指正!
首先:
package com.test;
public class ConsTest {
public static void main(String[] args) {
Integer a1 = 10;
Integer a2 = 10;
System.out.println(a1==a2);
}
}
上面的运行结果是true。为什么呢,因为Integer a1 = 10;这段语句已经把10放到了常量池,也就是说10已经是常量池中常量了,之后只要用到这个常量都会从常量池中去取,所以a2 = 10;这个10是从常量池中取的。也就是说a1 a2指向的是同一常量(或者对象?),所以返回的是true。
下面再看一个例子:
package com.test;
public class ConsTest {
public static void main(String[] args) {
Integer a1 = 128;
Integer a2 = 128;
System.out.println(a1==a2);
}
}
此时返回的结果却是false。那是因为常量池中,Integer、long这些常量池最大支持到127,超过127就不归常量池管了。所以a1 a2应该是在栈内存中分别开辟了空间存储128。因此a1 a2不是指向的同一空间,返回false。
package com.test;
public class ConsTest {
public static void main(String[] args) {
Integer a1 = 127;
Integer a2 = 127;
Integer a3 = new Integer(127);
System.out.println(a1==a2);
System.out.println(a1==a3);
}
}
理解了上面两个例子,我想这个也就好理解了。返回结果分别是true和false。a1指向的是常量池中的127,a3指向的是堆内存中的127
下面再来看一下String:
package com.test;
public class ConsTest {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str1.equals(str3));
}
}
其实让我好奇去了解常量池的初衷是因为上面的String str = new String("abc")这段代码;偶然在贴吧中看到,问到这段代码创建了几个对象。当时我想不是一个吗?但是看到那么多人都说2个,由于脑洞不够大,所以直接去搜了下。从而发现了原来还有常量池,自己果然太菜鸟了,且菜且努力!照我的理解,"abc"这段代码就相当于 String str = "abc" 所以如果abc已经在常量池中,创建的就是1个对象。否则就是2个。
正如上面代码展示的,输出结果分别是true,false,true。
第三个输出想必大家都应该都知道。这里只是为了强调==和equals的区别。==是比较对象的引用,equals比较是对象的值。
所以说,人必须要有求知欲啊,否则真的会‘一无所知’。
当然这点对大牛们来说都是很简单很基础的东西,对我来说这是个重要的进步吧。