Java中string类型什么情况下会加入字符串池

先简单介绍几个方法:

public native String intern();

当调用 intern 方法时,如果池中已经包含一个等于该 String 对象的字符串,由 equals(Object) 方法确定,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对该 String 对象的引用。
由此可见,对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

初始化一个新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要原始的显式副本,否则不需要使用此构造函数,因为字符串是不可变的。

这个方法也就是平时使用new关键字创建字符串调用的构造器

废话不说直接代码测试

第一种情况:直接使用双引号创建字符串

public void stringtest(){
        String str1="aismy";
        String str2="aismy";
        String str3=new String("aismy");
        System.out.println(str1==str2);
        System.out.println(str1==str3);
        System.out.println(str1==str3.intern());
    }

结果:true、false、true

分析原因:在String str1="aismy";时,将"aismy"添加到字符串常量池中,因此创建str2直接返回常量池中地址,因此str1==str2为true;而使用new 关键字创建的str3会重新在堆中创建一个String对象,因此str1和str3一个在常量池中一个在堆中,str1==str3为false;而str3.intern(),即将str3尝试放入常量池中,但是此时常量池已存在该字符串(在str1时就放入了),因此str3.intern()直接返回的是常量池中的该字符串地址,也就是str1的地址,因此str1==str3.intern()为true;

第二种情况:使用new关键字创建字符串对象

public void stringtest(){
       String str1=new String("aismy");
        System.out.println(str1.intern()==str1);
    }

结果:false

分析原因:在使用String str1=new String("aismy");创建str1对象时,此时常量池没有该字符串因此会创建两个对象,一个就是str1对象,除此之外再创建一个对象然后放入常量池中。

假设上述分析错误,也就是String str1=new String("aismy");并没有将“aismy”字符串放入常量池中,那么str1.intern()==str1应该返回true,因为若常量池中没有该字符串,那么调用str1.intern()也就是将str1引用地址放入常量池中,而返回结果为false,显然在调用str1.intern()之前,该字符串已存在与常量池中。

第三种情况:使用intern()

public void stringtest(){
       String str1=new StringBuilder("ai").append("smy").toString();
        System.out.println(str1.intern()==str1);
    }

结果:true

因为new StringBuilder("ai").append("smy")并没有将“aismy”放入常量池中,因此调用str1.intern()就是将str1的引用放入常量池中。

补充:jkd1.7之后字符串常量池被迁移至堆中,那么只需在常量池里记录首次出现的实力引用即可,也就是情况三中直接将str1引用放入常量池中。而在1.6中字符串常量池在方法区中(永久代)因此使用intern()会把首次遇到的字符串实例复制到永久代的字符串常量池中,返回的也是永久代里面的字符串实例,此时情况三结果为false

小结:情况二使用new关键字调用string构造器,会先判断该字符串在常量池中是否存在,不存在则会创建两个对象,而情况三则是调用intern()将字符串放入常量池中

本文参考:《深入理解java虚拟机》

错误之处,希望在评论区指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值