String面试1

本文详细探讨了Java中字符串的创建,包括字面量赋值和`new`创建,强调两者在内存中的区别。接着分析了不同类型的字符串拼接方式,如常量拼接、final变量拼接、变量与常量拼接以及变量与变量拼接,并解释了每次拼接时对象的生成情况。最后,文章深入讲解了`intern()`方法在JDK8中的行为,通过实例展示了其在不同场景下的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、字符串的创建

字面量直接赋值
先去常量池中找有没有这个字符串,有就直接指向常量池中该字符串;没有直接创建

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "world";

在这里插入图片描述
new 创建
new一个字符串时,做了两件事。首先在堆中生成了该字符串对象,然后去看常量池中有没有该字符串,如果有就不管了,没有就往常量池中添加一个

 String str1 = new String("hello");
 String str2 = new String("hello");
 String str3 = new String("world");

在这里插入图片描述
在堆中创建三个对象,常量池中两个共5个。
小结:两种创建方式一个在堆中,一个在常量池中。

2、字符串拼接

(1)常量拼接

String str = "hello"+"world";
//两边都是常量,在编译阶段会自动拼接变成
String str = "helloworld";

直接去常量池找 “helloworld”,有就直接指向它,没有就在常量池创建。
(2)有final的拼接

final String str1 = "hello";
final String str2 = "world";
String str3 = str1 + str2;

因为final 修饰的变量是常量,所以在编译期直接会变成

String str3 = "hello" + "world";

再根据常量拼接最终变成

String str3 = "hello" + "world";
3、变量和常量拼接

变量和常量拼接的时候会调用StringBuilderappend方法生成新对象。
情况1:

String str1 = "hello";
String str2 = str1 + "world";

在这里插入图片描述
str1在常量池中,world在常量池中,调用StringBuilder的append方法在堆中生成新对象
helloworld,str2指向堆中的helloworld 对象。共生成三个对象,常量池中有 helloworld,堆中有 helloworld.
情况2:

String str1 = new String("hello");
String str2 = str1 + "world";

在这里插入图片描述
先在堆中创建一个 hello,再把 hello 添加到常量池;然后把 world 添加到常量池,拼接的时候,会在堆中创建一个 helloworld。共4个对象,堆中 hellohelloworld 常量池中 hello world

4、变量和变量拼接

变量和变量拼接底层也会调用 StringBuilderappend方法生成新对象。
情况一:

String str1 = "hello";
String str2 = "world";
String str3 = str1 + str2;

在这里插入图片描述
这段代码,首先会有一个"hello"在常量池中,然后有个"world"在常量池,第三行代码会调用append方法,在堆中生成一个"helloworld"。所以总共有3个对象。
情况二:

String str1 = "hello";
String str2 = new String("world");
String str3 = str1 + str2;

在这里插入图片描述
这段代码,首先在常量池中搞一个"hello",然后在堆中new一个"world",同时把"world"也搞到常量池中去,第三步拼接就会在堆中生成一个"helloworld"。所以总共有4个对象。
情况三:

String str1 = new String("hello");
String str2 = new String("world");
String str3 = str1 + str2;

在这里插入图片描述
第一行代码创建了两个对象,堆中一个常量池一个,第二行代码也是一样,第三行代码就在堆中创建了一个"helloworld"。所以总共创建了5个对象。

5、intern方法(jdk8)

例一:

String str1 = new String("str")+new String("01");
str1.intern();
String str2 = "str01";
System.out.println(str2==str1); //true

在这里插入图片描述
在堆中创建一个str,同时添加到常量池中;再创建一个01,同事添加到常量池中,拼接。
在堆中生成对象str01, str1.intern() 把它的地址值添加到常量池中去;执行String str2 = str01时候,去常量池找 str01,发现常量池中有 x001地址值,为对应的要找的 str01。最终str1指向地址值为 x001 对象,str2 指向地址值为 x001对象。
在这里插入图片描述
例二:

String str1 = new String("str")+new String("01");
String str2 = "str01";
str1.intern();
System.out.println(str2==str1); //false

在这里插入图片描述
执行第二步时,往常量池中找str01,发现没有,那就添加一个;再执行str1.intern()时,发现常量池中有str01了,就不进行地址值的拷贝了。最终str1指向堆中的str01,str2指向常量池的str01,所以结果是false。
例三:

String str1 = new String("str")+new String("01");
String str2 = "str01";
str1 = str1.intern();
System.out.println(str2==str1);//true

就是把例二的str1.intern()改成str1 = str1.intern(),看看会有什么变化:
在这里插入图片描述
本来str1是指向堆中的str01的,然后重新将str1.intern()赋给str1,str1.intern()是指向常量池的,赋给str1后,所以此时str1也是指向常量池。所以结果就是true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值