详解String intern方法

一、弄清楚String对象的特点:

不可变的(final);

 

二、弄清楚+号和StringBuilder:

+号操作分n种情况,但只有一种情况等同于直接字符串,那就是常量值相加,像这样:

String str = "abc" + 123; 等同于String str = "abc123";

String str = "abc" + "def"; 等同于String str = "abcdef";

指令为证: 

      stack=1, locals=2, args_size=0
         0: ldc           #64                 // String abc123
         2: astore_0
         3: ldc           #66                 // String abcdef
         5: astore_1

除此之外,其他的相加一律视为StringBuilder对象,例如:

int i = 1;

String str = "abc" + i;

查看这两句的指令:

         0: bipush        123
         2: istore_0
         3: new           #64                 // class java/lang/StringBuilder
         6: dup
         7: ldc           #66                 // String abc
         9: invokespecial #68                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        12: iload_0
        13: invokevirtual #69                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        16: invokevirtual #72                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        19: astore_1
        20: getstatic     #43                 // Field java/lang/System.out:Ljava/io/PrintStream;

可以看到,其最终是通过StringBuilder来append字符串的。

 

三、弄清楚常量池在不同JDK版本下的存储位置

这一点对了解intern很重要,从JDK1.7开始,常量池就不放在永久代的方法区了,而是放在了堆中。同时,常量池也能够存储引用对象(指向堆地址)。

 

OK,了解了上面基础知识,再开始看intern,正所谓磨刀不误砍柴工。

 

四、执行intern方法后的效果

1.6:如果String对象在常量池中不存在,执行后,会在常量池中额外增加String常量对象;

1.7:如果String对象在常量池中不存在,会在常量池中创建一个指针指向堆中的String对象,很明显1.7要比1.6先进,至少节省了存储空间;

 

举例说明

1,先来个简单的例子

        String s1 = new String("abc");
        System.out.println(s1 == s1.intern());

输出:false

解释:这个很简单,可以看到s1指向堆中地址,而s1.intern()则返回常量池中的地址。

1.6

1.7

2,常见题目

String s1 = new String("a") + new String("b");

s1.intern();

String s2 = "ab";

Sysout.out.println(s1== s1.intern()); 

Sysout.out.println(s1== s2);

Sysout.out.println(s1.intern() == s2); 

解释:在1.7以后的版本中,String s1 = new String("a") + new String("b"); 这句话执行完,是不会往常量池中加常量对象ab的,只有a,b两个会加到常量池中。——这个前提要清楚。

JDK1.6,见左边图,s1.intern()后,会在常量池中加上ab对象,注意:是ab的值,不是引用;

JDK1.7,见右边图,s1.intern()后,会在常量池中加上指向堆地址的引用对象。

综上,比较==,只要看实线箭头最终指向哪里就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值