String的创建和拼接面试常考题详解

01 字符串的创建方法

String s1 = new String("hello");

首先字符串常量池中创建一个hello,在堆中创建String对象,对象的值执向为常量池中的hello,即是hello的内存地址。(如果常量池中已有hello则复用这个)

String s2 = "hello";

在字符串常量池中创建一个hello(如果常量池中已有hello则复用这个),s2变量指向常量池中的hello

02 非常关键的 intern()

intern()方法被调用的时候,如果字符串常量池中已经存在这个字符串对象了,就返回常量池中该字符串对象的地址;如果字符串常量池中不存在,就在常量池中创建一个指向该对象堆中实例的引用,并返回这个引用地址。

几个常考题

001 字符数组创建字符串
String s3 = new String(new char[]{'h','e','l','l','o'});
String s3_1 = "hello";
System.out.println(s3==s3_1);// false

首先在堆中创建一个字符数组,然后new一个新的字符串对象,对象利用这个字符数组进行初始化(将这个数组做了拷贝),如果是JDK9会先将char[]转为byte[]字节数组,s3所指向的字符串对象完全存储在堆中,且其字符(字节)数组与最开始创建的字符数组是不同的。

s3_1会引用字符串常量池中的 hello字符串。在这个例子中,s3 不会引用与 s3_1 相同的hello对象。

注意点:一开始创建的字符数组是个匿名对象,并没有指向它的引用,执行完该行代码后意味着它可能会被垃圾收集器回收,但是即使这个字符数组在逻辑上可以被垃圾收集,实际的回收时机是由垃圾收集器决定的,可能会在之后的某个时间点发生。此外,对于这种小对象,垃圾收集的效果可能不是很明显,因为它们可能会留在新生代中,直到新生代被清理

new String()不会检查字符串常量池中是否已经有相同的字符串。而是直接在堆内存中创建一个新的字符串对象。这意味着即使字符串的内容与字符串常量池中的某个字符串相同,这个新创建的字符串对象也不会引用常量池中的字符串。

002 intern()方法
String s4 = new String("1") + new String("1");
String s5 = s4.intern();
String s6 = new String("1");
String s7 = s6.intern();
System.out.println(s4==s5);// true
System.out.println(s6==s7);// false 

首先会创建两个字符串对象和常量池中字面量1(共用),创建StringBuilder对象,调用append()方法拼接字符串,然后toString(),实质是new String()创建一个新的字符串,但注意此时的11并不是字符串常量,没有存在字符串常量池中,s4所指向的字符串对象完全在堆中。

在对s4执行intern()方法时,由于常量池中没有11s4在堆中存放的11会被转移到常量池,并且s5会被赋予s4的引用,即此时都指向同一个字符串变量,即s4==s5

而对于s6s7s6也是在堆中new的新的字符串对象,存储的值在常量池中,调用intern()直接返回常量池中1的引用给s7,所以s6!=s7

003 字符串拼接

字符串拼接:常量+常量

String s8 = "a"+"b";
String s9 = "ab";
System.out.println(s8==s9); // true
// 下面的效果是一样的
final String s8_1 = "a";
final String s8_2 = "b";
String s8 = s8_1 + s8_9;

s8s9指向的都是常量,根据常量优化机制,编译的时候就会将a+b转为ab存到常量池中,所以s8s9是相同的引用。

字符串拼接:常量+变量

String s10 = "a";
String s11 = "b";
String s12 = "a" + "b";
String s13 = s1 + s2;
System.out.println(s4 == s3);//false

字符串拼接,但凡出现一个变量,由于 s10s11 是变量,Java 虚拟机不能确定它们的值在运行时是否会被改变,因此它会在堆内存中动态创建一个新的字符串对象 ab,并将 s13 指向这个新创建的对象,而s12会根据常量优化机制转为ab

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值