救救孩子吧QWQ
在《疯狂java讲义》中对于字符串有这么一段描述
“当 java 程序直接使用形如 "hello" 这样的字符串直接量(包括在编译时就可以计算出来的字符串值)时,JVM 将会使用常量池来管理这些字符串;当使用 new String("hello") 这样的表达式时,JVM 会先使用常量池来管理 "hello" 直接量,再调用 String 类的构造器来创建一个新的 String 对象,新创建的 String 对象被保存在堆内存中。换句话说,new String("hello") 一共产生了两个字符串对象”
可是在运行这一段代码时的结果却跟预想中的不一样
public static void main(String[] args) {
String s = new String("1");
String s2 = "1";
s.intern();
System.out.println(s == s2); //false
String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4); //false 预想中的是 true
// String s3 = new String("11") 的时候控制台输出结果也是 false
}
原书的解释为:
“这样,首先执行String s4 = "11";声明 s4 的时候常量池中是不存在“11”对象的,执行完毕后,“11“对象是 s4 声明产生的新对象。然后再执行s3.intern();时,常量池中“11”对象已经存在了,因此 s3 和 s4 的引用是不同的。”
但是根据开头的内容,我有以下两个问题
1.String s3 = new String("1") + new String("1") 中,字符串常量池(constant pool) 专门用于管理在编译时被确定并保存在已编译的 .class 文件中的一些数据。由此在这个时候常量池不是应该已经存储了在编译时被确定的字符串"11"(因为 "1" + "1" = "11"),那么在 s4 指向的地址不是应该就是字符串常量池的 “11” 的地址吗?为什么会说在 s4 的时候常量池中不存在 “11” 对象。
2.在 new String("11") 的时候不是应该已经将字符串直接量借给常量池管理了吗?那么 s4 不是应该可以从常量池中直接拿到,两个的地址不是应该一样吗?
请大佬解惑,小弟先在此跪谢了
1.new String("1")是创建对象,在编译期并不确定,所以new String("1") + new String("1") 字符串常量池中只会有“1”,但是“1”+“1”在编译期就会确定,才会达到你想要的效果
2.要搞清楚这个问题你要知道String s = new String("1");String s2 = "1";的区别,一个是new了String类对象的引用,一个是常量值的引用;你new String()一百个一样的字符串它们还是不同的对象引用;
接下来是intern(),首先这个方法是有返回值的,你并没有用到,返回的结果是常量的引用,而不是类对象的引用
就像这样:
String s3 = new String("1") + new String("1");
String s4 = "11";
s3 = s3.intern();
System.out.println(s3 == s4);
这样结果才会是true