java常量池理解

String类两种不同的创建方式

String s1 = "zheng";    //第一种创建方式
String s2 = new String("junxiang");    //第二种创建方式

第一种创建方式是编译期在常量池中创建对象,如果常量池中已经存在"zheng"这个String对象,就将地址赋给s1.第二种创建方式是运行期在堆中创建对象,无论堆中是否已有都会重新创建一个对象。

String s1 = new String("xyz");
String s2 = new String("xyz");

上边创建了3个String对象,编译期常量池创建了1个,运行期堆中创建了2个。

例1:

String s1 = "xyz";
String s2 = "xyz";
System.out.println(s1==s2);
//输出true,因为如果在常量池中已有相同的对象则不再创建而将地址赋给s2。

例2:

String s1 = new String("xyz");
String s2 = new String("xyz");
System.out.println(s1 == s2);
//输出结果是false,因为采用new在堆中每次都会创建一个新对象。

例3:

String x = "zheng";
String y = "jx";
String s = "jxzheng";
String s1 = y + x;
String s2 = "jx" + "zheng";
System.out.println(s1 == s);//输出false,因为字符串连接操作数中有变量。所以运行期才能确定,存在堆中。
System.out.println(s2 == s);//输出true,因为字符串连接操作数都是字符串常量,编译期即可确定,存在常量池中。

总结为以下四条规律:

  1,单独使用""引号创建的字符串都是常量,编译期就已经确定存储到String Pool中;

  2,使用new String("")创建的对象会存储到heap中,是运行期新创建的;

  3,使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到String Pool中;

  4,使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中;

 String.intern()

String s1 = new String("xyz");
s1 = s1.intern();//intern()返回在常量池中这个String对象的引用。如果常量池中已经存在这个String对象,则直接返回该对象的引用,否则,在常量池中创建对象并返回引用。

例4:

String s3 = new String("1") + new String("2");
s3.intern();
String s4 = "12"; System.out.println(s3
== s4);//jdk7/8输出结果为true

原因是jdk7中的常量池不是在方法区而是在堆中,可以直接存储对象的引用。所以s4和s3指向的是同一个对象。这篇博客String.intern() Test of JDK6 And JDK7讲解比较清楚。

参考博客:

String之常量池小结

Java堆栈和常量池

Java常量池理解与总结

Java常量池详解之一道面试题

你可能感兴趣的:(java常量池理解)