public class Test { public static void main(String args[]) { String s1 = "Java"; String s2 = "Java"; System.out.println(s1 == s2); // true } }
程序只創建了一個"Java"字符串對象,存放在常量池中,故s1 == s2結果為true,兩個變量都指向了同一個對象。
常量池專門用於管理在編譯時被確定並被保存在已編譯的.class文件中的一些數據。如字符串常量,類、方法中的常量。
public class Test { public static void main(String args[]) {
String s3 = new String("Java"); String s4 = new String("Java"); System.out.println(s3 == s4); // false } }
"Java"直接量與new String("Java")的區別:前者只創建於常量池中。后者先在常量池中創建一個對象,再創建一個新的String對象於
堆內存中,換句話說new String("Java")創建了兩個對象(“Java”第一次出現)。
String s3 = new String("Java");創建了兩個String對象,一個存於常量池中,一個於堆內存中且由s3指向。
String s4 = new String("Java");由於常量池中已經存在"Java"對象,故只創建一個對象於對內存中由s4指向。
故s3 == s4的結果為false。
public class Test { public static void main(String args[]) { String s5 = "HelloJava"; String s6 = "Hello" + "Java"; System.out.println(s5 == s6); // true } }
由於常量的值在編譯的時候就被確定(優化)了。在這里,"Hello"和"Java"都是常量,因此變量s6的值在編譯時就可以確定。
s6指向常量池中的"HelloJava"對象,故s5 == s6 的結果為true。
public class Test { public static void main(String args[]) { String s5 = "HelloJava"; String s7 = "Hello"; String s8 = "Java"; String s9 = s7 + s8; System.out.println(s5 == s9); // false } }
s9由兩個String變量相加的得到,不能在編譯時就確定下來,故不能引用常量池中的對象,而是在堆中創建了一個新的String對象並由s9指向。
故s5 == s9 結果為false
public class Test { public static void main(String args[]) { String s5 = "HelloJava"; final String s7 = "Hello"; final String s8 = "Java"; String s9 = s7 + s8; System.out.println(s5 == s9); // true } }
這里s7與s8位由final修飾為宏變量,編譯器會把程序中所有用到該變量的地方直接替換成該變量的值,故s9編譯時就確定了。指向
常量池中的對象。