为何相同值的String未指向字符串常量池中的同一对象?
关于字符串常量池与String对象指向的疑惑解答
嘿,这个问题我刚入门Java的时候也踩过坑!先帮你捋清楚核心原因——你看到的s2没有指向常量池已有对象的情况,大概率是因为创建s2时用了new String("Hello"),而不是直接用双引号声明。
咱们一步步拆解细节:
- 当你用
s1 = "Hello"这种双引号直接赋值时,JVM会先去字符串常量池里查找是否存在值为"Hello"的对象:- 如果不存在,就会在常量池里创建这个对象,再让s1指向它;
- 如果已经存在(比如之前s1已经创建过),就直接让新引用指向这个已有的常量池对象。
- 但如果是用
s2 = new String("Hello")来创建,逻辑就完全不同了:- JVM会先检查常量池里有没有"Hello",如果没有就先在常量池创建一个;
- 然后一定会在堆内存里新建一个String对象,这个堆对象的内部会引用常量池里的"Hello",最后让s2指向堆里的这个新对象,而非常量池里的那个。
- 你提到的s3能指向已有对象,应该就是用了
s3 = "Hello"这种直接赋值的方式,所以它会直接复用常量池里的"Hello",和s1指向同一个对象。
举个代码例子更直观:
String s1 = "Hello"; // 常量池创建"Hello",s1指向它 String s2 = new String("Hello"); // 堆里新建对象,s2指向堆对象 String s3 = "Hello"; // 直接复用常量池的"Hello",s3和s1指向同一个对象 System.out.println(s1 == s3); // 输出true,因为指向同一个常量池对象 System.out.println(s1 == s2); // 输出false,因为s1指向常量池,s2指向堆对象
另外补充个小知识点:如果想让new String("Hello")也复用常量池的对象,可以调用intern()方法,比如s2 = new String("Hello").intern();,这时候s2就会指向常量池里的"Hello"了。
内容的提问来源于stack exchange,提问作者user9608350
相关产品推荐
相关产品推荐

