最近LZ在看一些博客的时候遇到一个问题,后来百度了才知道java有一个很重要的知识点,就是常量池问题。先看下面这个问题:
public class T
{
public static void main(String[] args)
{
testFinal();
}
public static void testFinal()
{
String s1 = "ab";
String s2 = "a";
String s4 = s2 + "b";
System.out.println(s2 + " " + s4);
System.out.println(s1 == s4);
final String s3 = "a";
String s5 = s3 + "b";
System.out.println(s3 + " " + s5);
System.out.println(s1 == s5);
}
}
上述两个输出的结果分别是什么?
得到的结果是false和true。这是什么原因呢?主要就是这个常量池在起作用。首先得理解常量池技术
java中的常量池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有就创建一个),则在需要重复创建相等变量时节省了很多时间。常量池其实就是一个内存空间,常量池存在于方法区中。
JVM的编译器将源程序编译成class文件后,会用一部分字节分类存储这些粗体代码。而这些字节我们成为常量池。其中包括了类、方法和接口等中的常量,也包括字符创常量,如String s = "java"这种。对于这种方式,在编译时,会被识别为同一字符串,自动优化成常量,所以如果有多个字符创"java"时候,则他们会引用自同一String对象。也就是说String s = "java" 其中"java"值在JAVA程序编译期就确定下来了的。(大家可以用UE编辑器或其它文本编辑工具在打开class文件后的字节码文件中看到这个java值)。这个java存在在常量池中。注意:常量池只存储文字字符串值,不存储符号引用。
而在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象.String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回一个引用,没有则添加自己的字符串进入常量池,注意:只是字符串部分。所以这时会存在2份拷贝,常量池的部分被String类私有并管理,自己的那份按对象生命周期继续使用。String s = new String("java");语句,到底创建了几个对象呢? "java"本身就是常量池中的一个对象,而在运行时执行new String()时,将常量池中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有。所以这条语句就创建了2个String对象。