String面试总结

前端时间笔者去腾讯面试,面试官给的第一道题就是String各种操作的问题,虽然之前看过这些知识,当时笔者一时也没想起来,好记性不如烂笔头呀,这里做下笔记,以防下次再问。

一、无‘+’操作符时的比较

//代码1

String s1 =new String("Hello world");            

String s2 =new String("Hello world");     

String s3= "Hello world";     

String s4= "Hello world";   

问题1:System.out.println(s1==s2);  // false   

问题2:System.out.println(s2==s3);  // false     

问题3:System.out.println(s3==s4);  // true   

问题4:System.out.println(s2.equals(s4));  // true 

 

解析:

问题1:s1==s2比较的地址值而不是对象,s1与s2在堆内存中是两个不懂的对象因此地址肯定不一样。

问题2:s2在堆内存中新建了一个对象,存储的是该对象的地址值,而s3存储在常量池中,对应的地址值是intern字符串对象 ,又叫拘留字符串对象。因此s2与s3的地址不一样。(常量池中的字符串常量唯一且不重复,每个常量对象对应的拘留字符串对象也是唯一不重复的)

问题3:s3与s4指向的都是常量池中同一个字面量所对应的同一个intern对象(也可以简单理解为常量池中的同一个对象),所以是相等的。

问题4:s2与s4比较的是单纯的值是否相等,当然是true了。

二、有‘+’操作符时的比较

//代码2  

String s1 = "ab";                                          

String s2 = "cd";                                       

String s3 = s1+s2;                                      

String s4 = "abcd";  

String s5="ab"+"cd";

问题1:System.out.println(s3==s4); // false  

问题2:System.out.println(s4==s5); //true  

解析:

问题1:Sun规定String类型运算的时new了StringBuilder对象,然后用append()方法追加字符串,最终以StringBuilder的toString()方法返回,而它的toString()方法是直接new了一个String对象返回的,那么 == 去比较两个String对象的地址,肯定是不相等的。

String s3 = s1+s2;     这行代码实际上创建了StringBuilder对象、toString()时的String对象,一共两个对象,如果此时常量池中没有"abcd"这个对象,那么在常量池中还会创建一个对象也就是一共3个对象。
问题2:

String s5="ab"+"cd";这行代码在编译时期就已经被编译器优化为String s5 = "abcd"了,所以s4与s5是相等的。指向的是常量池中同一个对象。

代码2的堆中实际上有五个字符串对象:三个拘留字符串对象( "ab"、"cd"、"abcd")、一个String对象(s3指向的堆内存的"abcd"对象)和一个StringBuilder对象(s1+s2时产生的)。

三、有final修饰时‘+’操作符的比较

String a = "hello2";

final String b = "hello";

String d = "hello";

String c = b + 2;

String e = d + 2;

System.out.println((a == c)); //true

System.out.println((a == e));//false

为什么第一个比较结果为true,而第二个比较结果为fasle。这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。这种和C语言中的宏替换有点像。因此在上面的一段代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的 值。而对于变量d的访问却需要在运行时通过链接来进行。想必其中的区别大家应该明白了,不过要注意,只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化。

如果在编译期间不能确切知道final变量值,就不会直接替换,如下:

String a = "hello2";

final String b = getHello();

String c = b + 2;

System.out.println((a == c)); //false

public static String getHello() { return "hello"; }

 

 

参考1:https://www.iteye.com/topic/522167

参考2:https://blog.csdn.net/qq_27657429/article/details/77882191

参考3:https://www.cnblogs.com/sister/p/4706024.html

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值