字符串进入常量池时机(intern方法)

先来一段简单的代码SeeSee

public class Test0{
    public static String s1="static";  // 第一句
    public static void main(String[] args) {
        String s1=new String("he")+new String("llo"); //第二句-hello1
        s1.intern();   //将 堆中新建的对象"hello" 存入字符串常量池
        String s2="hello";  //第三句-hello2
        System.out.println(s1==s2);//输出 true。
    }
}

类加载以后,“he” “llo” “hello” 对象实例在堆上创建,并且引用在 字符串常量池中驻留。 我们将这个 "hello"对象实例叫做 hello1.

第二句,s1是在堆上新创建的 "hello"对象实例,叫做 hello2.当执行到intern()语句时, hello2 equals hello1 都是 “hello” 。但是hello1 和 hello2在堆中的地址是不一样的,那么字符串常量池中原本存储的是hello1的地址,现在是会依旧使用hello1的地址还是 更新 为 hello2的地址?这是问题1

为了描述的方便。我们将intern()执行后,字符串常量池中的"hello"引用假设为 hello3 . hello3指向 hello1 或者hello2. 这取决于问题1的答案.

第三句,直接将s2赋值为 常量池中的 hello3所指向的字符串.

但是最终输出结果 是true 。 这是说明了 hello3所指向的是hello2.

通过结果推测:问题1的答案就是,字符串常量池更新了。

举个反例:

class Test1{
    public static void main(String[] args) {
        String s1=new String("he")+new String("llo");//hello1
        String s2=new String("h")+new String("ello");//hello2
        String s3=s1.intern();
        String s4=s2.intern();
        System.out.println(s1==s3);
        System.out.println(s1==s4);
    }
}	
/*打印结果
true
true
*/

前面我们的答案是字符串常量池更新了。

为了方便 s1 的 “hello” 是 hello1 . s2 的 “hello” 是 hello2 .

hello2和hello1是不同对象具有不同地址,但是内容都是"hello"。

s3就等于 hello1, s4=hello2

因此 s1==s3 是肯定的。指向同一个"hello"对象hello1.

但是 s1==s4 应该是错的。因为 一个指向hello1 一个指向hello2.

但是结果却是两个都是true,这个问题当时是百思不得其解;一开始我的想法是是不是intern()方法优先选择了先创建的s1。

one hundred years后找到了答案:
1.是在类加载过程中就已经被更新了。
2.是在真正执行代码时,遇到字面量或者intern()语句,就将其尝试加入字符串常量池。
3.两者都具备, 类加载过程是初始化常量池。 执行代码时是新增常量池的内容。并且对于常量池中已有的字面量,不采取更新措施

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值