String字符串的常量池

本文引用自:https://www.oschina.net/question/2709988_2278459   

题目:

String s1 = "Programming";

String s2 = new String("Programming");

String s3 = "Program";

String s4 = "ming";

String s5 = "Program" + "ming";

String s6 = s3 + s4;

 

System.out.println(s1 == s2); //false

System.out.println(s1 == s5); //true 

System.out.println(s1 == s6); //false 

System.out.println(s1 == s6.intern()); //true 

System.out.println(s2 == s2.intern()); //false 

 

解释:

必备知识:

  1. java 程序在运行的时候, 会创建一个字符串缓冲池。对于诸如 String s1 ="Programming"; String s3 = "Program"; String s4 = "ming"; 这些字符串常量,程序首先会在这个 String 缓冲池中寻找相同值的对象。若它们在池中不存在,程序则将这些字符串常量创建于池中。若在池中找到了相同值得对象,则这个找到的对象的引用,就是新变量的引用。由此可见,字符串常量池中一个给定值得对象,最多只有一个。
  2. 用操作符 new 创建的字符串对象, 如 String s2 = new String("Programming");, 或者有字符串变量、操作符 '+' 参与的表达式,如 String s6 = s3 + s4; 这样得到的引用,都要放到内存(堆heap)中保存。故,在堆中,若有几个值相同的对象,它们分别都会有各自的地址。
  3. 字符串的一个成员方法 public String intern(),返回字符串对象的规范化表示形式。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。

解释:

  1. 由必备知识 1,2所示,s1创建于字符串缓冲池,而s2创建于内存(堆)中,尽管二者内容都是"Programming",但地址不在一个区,故比较地址的结果为 false。
  2. 至于 String s5 = "Program" + "ming";的操作, 由于表达式的两个算子都是字符串常量,所以操作始终在池内进行。在池内找到 "Program" 和 "ming"之后,将两者连接成 "Programming", 然后,又在池内找到了相同值的对象s1,于是就将这个地址,赋予 s5。因此,比较s1 和 s5 的地址,当然相同,结果为 true。
  3. 如预备知识1、2所示,s6的地址,存在堆里。而s1的地址存在池里。尽管两者值相同,但地址一定不同,结果为 false。
  4. 如预备知识3所示,因为s6调用了它的成员方法inner(),结果返回了一个在池中的、具有相同值“Programming”的对象s1的地址。用它和 s1的地址相比较,当然相等,结果为 true。
  5. 如预备知识3所示,s2的地址在堆里,s2.inner() 的地址在池里。一个在堆中,一个在池内,二者比较,肯定不等,结果为false。
  6. 你写的代码是String s5 = "Program" + "ming";你可以反编译你对象的class文件

    看到的代码其实就是String s5 = "Programming"; 这是JDK帮你做得优化

    第三个

    JDK没法优化,不知道S1,S2是什么,所以就产生了一个新的对象

你可能感兴趣的:(String字符串的常量池)