Java 知识-- Java 中的 String 相等?
本文最后更新于:3 个月前
(本文基于 JDK 1.7 及以上)
-
test1
String str1 = “hello word"; String str2 ="hello" +" word"; System.out.println(str1==str2); // true
这种情况下编译器会对 str2 进行优化,直接优化成 “hello word”,str1==st2
-
test2
String s1 = "hello word"; // s1 此时在堆上(字符串常量池中)创建了一个 String 对象,并把对象加入到字符串常量池的引用中 String s2 = new String("hello word"); // s2 会在堆上生成一个 String 对象,因为字符串常量池中已经有了,那么不会创建新的 String 对象,会把字符串常量池中引用的对象直接返回给 s2 所创建的 String 对象 // 但是 s2 和 s1 所引用的对象的地址还是不相同的 // 因为 s2 其实还可以看成一个引用,它指向 s1 System.out.println(s1==s2); // false System.out.println(s2.intern()=="Hello World"); // intern() 方法会去字符串常量池中找有没有字符串对象 "Hello Word",这里找到了最开始 s1 存入的字符串常量,所以直接返回字符串常量池中的 String 对象地址 // true
-
test3
String s1 = new String("1"); // 在堆上生成一个 String 对象,并且建立在字符串常量池中的 "1" String 对象引用 String s2 = "1"; // 把 s2 引用直接指向字符串常量池中的 "1" 对象 System.out.println(s1 == s2); // s1 和 s2 引用的地址不相同,结果为 false System.out.println(s1.intern()=="1"); // intern() 方法会去字符串常量池中找有没有字符串对象 "1",这里找到了最开始 s1 存入的字符串常量
test2 和 test3 说明无论直接赋值和 new String 顺序如何改变,只要一个在常量池,一个是每次在堆上的新生成的对象,他们内存地址就一定不会相同
-
test4
String s1 = new String("1")+new String("1"); // 这里仅仅会在字符串常量池生成一个字符串对象 "1",和两个 String 对象,并且 String 对象指向到字符串对象 // 因为这里两个 String 对象相加,而不是 new String("11"),所以这里虽然在堆上生成了第三个 String 对象,但是没有把对象的引用加入到字符串常量池中 // 即此时并没有在字符串常量池中产生 "11" 这个字符串对象 s1.intern(); // 对于这个方法,JDK 1.7 中不会在字符串常量池生成一个 "11" 对象了,只是在字符串常量池中建立一个对于堆上字符串对象的引用 String s2 = "11"; // 这里去字符串常量池中查找,找到了一个指向堆上字符串对象的引用,即上面 s1 创建的对象 System.out.println(s1 == s2); // true
-
test5
为了验证上面 test4 中 s1 new String 时并没有加入到字符串常量池中:
String s1 = new String("1")+new String("1"); // 与上面的区别在于这里 s2 和 s1.intern() 方法顺序不同了 String s2 = "11"; // 这里直接看到字符串常量池中没有 "11" 这个字符串对象,那么直接创建 s1.intern(); // 此时返回了上面 s2 创建的字符串对象,但是没有意义了 System.out.println(s1 == s2); // s1 在 堆上面,s2 在字符串常量池,结果为 false // false
-
test6
String str1 = "b"; // 编译器认为 str1 是变量,只会在运行时确定 str2 的值 // 此时会在堆上产生一个字符串常量 String str2 = "a" + str1; String str12 = "ab"; System.out.println(str1 = str12); // false
// 和上面代码不同的地方在于 str1 加了 final 修饰,编译器会认为这个 str1 是常量进而在编译时直接优化 final String str1 = "b"; // 在编译时会直接变成 str2 = "ab"; String str2 = "a" + str1; String str12 = "ab"; System.out.println(str1 = str12); // true
本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 。转载请注明出处!