[面试题]一道看似简单的面试题引发的血案

先上题目:

以下代码运行结果是( )

String s1 = "hello";
String s2 = "he";
String s3 = s2 + "llo";
System.out.println(s1 == s3);

看到使用直接赋值理所当然想到常量池,然后以为以+拼接出来的字符串当然也会放入常量池就填了True

然后惨被打脸

 

创建字符串对象时,一般有几种情况:
1,直接赋值:直接赋值时会先去常量池寻找,如果常量池有该字符常量,则直接让变量指向常量池引用;如果没有就将字符串放入常量池并让变量指向
2,使用new创建:会在堆内存分配空间,不会用到常量池,如果要用,就要调intern()方法去常量池"注册":

           如果常量池有该字符串常量,则让对象指向常量池引用;如果没有,在jdk1.7以前,会直接将对象中的字符串拷贝到常量池中并返回引用;
           如果jdk是1.7及以后版本,会直接让常量池常量指向堆内存中对象引用,相当于"挂名"
3,使用"+"拼接字符时:如果拼接的是final修饰的字符变量(final字符在编译阶段都会被替换为常量)或者常量,编译器会直接拼接字符串,并在常量池"注册"
    如果不是常量或者final修饰的字符串,底层会通过StringBuilder拼接,所以引用会变;
                     延伸1:如果拼接字符串中出现null时,根据StringBuilder.append()方法源码可知,并不会出现NPE,而是将"null"拼进去
                     延伸2:如果代码中用到很多拼接字符串时,有必要考虑使用StringBuilder处理,这样避免了在底层new过多StringBuilder临时对象

intern方法:功能相当于将字符串"注册"到常量池

代码演示:


String s2 = new String("1");
s2.intern();
String s1 = "1";
System.out.println(s1 == s2);//false 在构建s2前已经用到了常量,并注册到了常量池

String s3 = s1+"1";
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);//true(jdk1.7以前为false) 注册后常量池指向了s3
System.out.println(s3.intern() == s3);//true 套娃


final String s1 = "1";
final String s2 = "2";
String s3 = s1+s2;
String s4 = new String("12");
System.out.println(s3 == s4.intern());//true 这里s3实质上相当于常量

 

如有不对,欢迎指正!

参考1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值