欢迎选择我的课程,让我们一起见证您的进步~~
上面的代码, 我用 JDK6 和 JDK7 分别运行了一下, 结果如下:
JDK6: false, false JDK7: false, false
没有如题主所说的是 true, false. 我想究其原因, 主要有两点:
字符串 "java" 比较特殊, 它在常量池中固定存在的
因此代码
String str1 = new StringBuilder("ja").append("va").toString(); System.out.println(str1.intern() == str1);
str1.intern() 返回的是常量池中的对象, 于是和堆上的 str1 就不是同一个对象了.
"python" 字符串已经在代码中出现了, 因此会添加到常量池中.
第二部分的代码中, 因为出现了字面常量 "python", 因此它会添加到常量池中.而:
String str2 = new StringBuilder("python").append("").toString(); System.out.println(str2.intern() == str2);
为字符串 "python" 添加了空字符串 "", 因此相当于没有添加新的字符串常量, 进而 str2.intern() 返回的还是常量池中的对象.
其实上面的题目可以引申一下, 例如:
// 1 String str1 = new StringBuilder("ja").append("va1").toString(); System.out.println(str1.intern() == str1); // true // 2 String str2 = new StringBuilder("python").append("").toString(); System.out.println(str2.intern() == str2); // false
我仅仅把第一部分的代码 "StringBuilder("ja").append("va")" 改为 "StringBuilder("ja").append("va1")". 这样改动会有什么不同的结果吗?我们来看看在 JDK6 和 JDK7 下运行的结果吧:
JDK6: false, false JDK7: true, false
为什么 JDK6 和 JDK7 的运行结果不一样呢?其实这涉及到了不同的 JDK 对 intern() 方法的不同实现:在 JDK6 及以前的 JDK 中:
intern() 方法会把首次遇到的字符串实例 **复制** 到永久代中, 然后返回永久代中的实例.
而对于 JDK7 以及之上的JDK:
当遇到第一次出现的字符串时, intern() **不再复制实例**, 而是在常量池中记录首次出现的实例的引用, 并且 intern() 返回的是此实例引用.
根据 JDK6 和 JDK7 的 intern() 方法的区别, 我们就知道了例子:
在不同的 JDK 返回不同结果的原因了:在 JDK6 中, "java1" 是第一次出现的字符串常量, 因此会被复制到常量池中, intern() 方法返回的是常量池中的对象, 因此与堆上的 str1 就不等了.而在 JDK7 中, "java1" 是第一次出现的字符串常量, 但是 intern() 方法仅仅是将这个对象的引用添加到常量池中, 并没有和 JDK6 一样拷贝一个新对象到常量池, 因此 intern() 方法返回的引用其实还是和原来的 str1 相等.
上面的代码, 我用 JDK6 和 JDK7 分别运行了一下, 结果如下:
没有如题主所说的是 true, false. 我想究其原因, 主要有两点:
字符串 "java" 比较特殊, 它在常量池中固定存在的
因此代码
str1.intern() 返回的是常量池中的对象, 于是和堆上的 str1 就不是同一个对象了.
"python" 字符串已经在代码中出现了, 因此会添加到常量池中.
第二部分的代码中, 因为出现了字面常量 "python", 因此它会添加到常量池中.
而:
为字符串 "python" 添加了空字符串 "", 因此相当于没有添加新的字符串常量, 进而 str2.intern() 返回的还是常量池中的对象.
其实上面的题目可以引申一下, 例如:
我仅仅把第一部分的代码 "StringBuilder("ja").append("va")" 改为 "StringBuilder("ja").append("va1")". 这样改动会有什么不同的结果吗?
我们来看看在 JDK6 和 JDK7 下运行的结果吧:
为什么 JDK6 和 JDK7 的运行结果不一样呢?
其实这涉及到了不同的 JDK 对 intern() 方法的不同实现:
在 JDK6 及以前的 JDK 中:
而对于 JDK7 以及之上的JDK:
根据 JDK6 和 JDK7 的 intern() 方法的区别, 我们就知道了例子:
在不同的 JDK 返回不同结果的原因了:
在 JDK6 中, "java1" 是第一次出现的字符串常量, 因此会被复制到常量池中, intern() 方法返回的是常量池中的对象, 因此与堆上的 str1 就不等了.
而在 JDK7 中, "java1" 是第一次出现的字符串常量, 但是 intern() 方法仅仅是将这个对象的引用添加到常量池中, 并没有和 JDK6 一样拷贝一个新对象到常量池, 因此 intern() 方法返回的引用其实还是和原来的 str1 相等.