字符串常量与intern方法

我们可以new String对象来创建一个字符串
String s = new String(“sp”);
但是非常不建议这么用,可以使用字面量来替代
String s = “sp”;

这是为什么呢?我们知道new 关键字是会创建对象的,无论是否之前创建过


String a = new String("a");

String b = new String("a");

System.out.println(a == b);

结果输出false ,证明这是两个对象

那么使用字面量创建有什么好处呢?

String a = "a";

String b = "a";

System.out.println(a == b);

结果输出true,哦?有点意思了——他们指向同一个对象
也就是说,String b = “a”; 不再创建新的对象。
好像挺好的, 但是这是为什么呢?

在类加载的过程中,类的class文件的信息会被解析到内存的方法区里。
class文件里常量池里大部分数据会被加载到“运行时常量池”,包括String的字面量;但同时“Hello”字符串的一个引用会被存到同样在“非堆”区域的“字符串常量池”中,而"Hello"本体还是和所有对象一样,创建在Java堆中。

什么意思呢?就是java运行时的内存里 有一个叫做字符串常量池的地方,以字面量的方式创建的字符串,会被拷贝一份引用放在这里,当下次创建相同(equalse true)的字符串时,就直接返回这里的引用。

哦,那也就是说,我下次再定义 String c = “a” 是不会在内存创建另外一个字符串的,这样节约了内存呢

String.intern() 方法的作用

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
–from jdk 1.7

我来大概翻译一下,当调用Intern方法时,如果池中包含一个与此字符串对象『相等』的字符串,池里的字符串将会返回,否则这个字符串对象就会加入到池中,并且会返回一个此字符串对象的引用

String a = new String("a"); //堆中放对象 ,常量池中放引用

String a1 = a.intern(); //a1 = 字符串常量池中的引用

String b = "a"; //b = 字符串常量池中的引用

System.out.println(a1 == b); //true

结果返回 true
让我们来分析一下
String a = new String(“a”);会在堆中创建一个对象,并在常量池中放一个指向这个字符串对象的引用
String b = “a”; 返回指向常量池中字符串的引用
a.intern() 返回常量池中指向等于a(equalse(a))的字符串对象的引用
所以 a.intern() 和b 都是指向字符串常量池中的字符串对象
有点绕口…

在java 1.7 常量池不在是在永久代 而是在堆中
常量池中也不在存放字符串对象,而是对象的引用(既然常量池在堆中,那么就没必要再在常量池中放字符串对象了)

这样看来 第一次创建字符串时 new String 还是字面量是一样的,不过如果再new 相同的对象堆中会重复创建,而使用字面量不会

一个有意思的坑

        String str1 = new StringBuilder("计算机").append("软件").toString();
        System.out.println(str1.intern() == str1);
        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern() == str2);

java 1.7+

true false

str1很好理解 因为字符串是第一次出现 所以会在字符串常量池存一个引用 都指向堆里的对象

str2 很坑因为"java"并不是第一次出现,第一次是在sun.misc.Version,所以这里str2 是一个新的对象,堆中存在两个"java"对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值