java面试中关于String的常见问题

本文详细解析了 Java 中 String 对象的创建过程及内存分配情况,包括直接赋值与 new 创建的区别,以及 intern() 方法的作用原理。通过实例展示了字符串拼接时 StringPool 和堆内存中的变化。
[b]以下内容是看了浪曦教学视频做的笔记![/b]

问题1:
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");

System.out.println(s == s1);
System.out.println(s == s2);
System.out.println(s1 == s2);

请问以上程序执行结果是什么?

第一句执行后内存中有两个对象,而不是一个。一个由new String("abc")中的"abc"在String Pool里生成一个值为"abc"的对象;第二个由new在堆里产生一个值为"abc"的对象,该对象完全是String Pool里的"abc"的一个拷贝。变量s最后指向堆中产生的"abc"对象;
第二句执行时,s1先去String Pool找是否有值为"abc"的对象,很显然在上一步中java已经在String Pool里生成一个"abc"对象了,所以s1直接指向String Pool中的这个"abc";
第三句中又有一个new,在java中凡遇到new时,都会在堆里产生一个新的对象。因此,该句执行后堆里又多了一个"abc"对象,这与执行第一句后生成的"abc"是不同的两个对象,s2最后指向这个新生成的对象。
因此,执行后面的打印语句的结果是三个[b]false[/b]

问题2:
System.out.println(s == s.intern());
System.out.println(s1 == s1.intern());
System.out.println(s1.intern() == s2.intern());

请问以上程序执行结果是什么?

设s为String类型的变量,当执行s.intern()时,java先在String Pool里找与字符串变量s相等(用equals()方法)的字符串,若有则将其引用返回;若没有则在String Pool里创建一个与s的值相等的字符串对象,并将其引用返回。从中我们可以总结出intern()方法无论如何都将返回String Pool里的字符串对象的引用。
因此,以上程序执行的结果是[b]false[/b],[b]true[/b],[b]true[/b]。
PS:设s和t为两个字符串变量,若有s.equals(t),必有s.intern() == t.intern();
PS:"=="永远比较的是两边对象的地址是否相等。

问题3:
String hello = "hello";
String hel = "hel";
String lo = "lo";
System.out.println(hello == "hel" + "lo");
System.out.println(hello == "hel" + lo);

请问以上程序执行结果是什么?

前三句在String Pool里分别产生“hello”、“hel”、“lo”三个常量字符串对象
当做第一个加法连接时,+号两边都是常量字符串,java就会将两者拼起来后到String Pool里找与之相等(用equals)的字符串,若存在则将其地址返回;不存在则在String Pool里新建一个常量对象,其值等于拼接后的字符串,并将其地址返回。
第二个+号两边有一个是变量,此时,java会在堆里新建一个对象,其值是两字符串拼接后的值,此时返回的地址是堆中新对象的地址。
所以,第一句做+连接后返回String Pool中“hello”的地址,显然与变量hello的地址相等;
第二句返回的是堆中地址,显然与变量hello的地址不等;
### Java 中关于 String 的常见面试题 #### 1. **String 是不可变的吗?** 是的,`String` 在 Java 中是不可变的。一旦创建了一个 `String` 对象,其内容就不能更改[^2]。每次修改字符串的操作实际上都会返回一个新的 `String` 实例。这种特性有助于线程安全以及缓存哈希值等功能。 #### 2. **String str1 = "abc"; 与 String str1 = new String("abc"); 的区别是什么?** 使用 `"abc"` 方式定义的字符串会被直接存储在字符串常量池中;而通过 `new String("abc")` 创建的对象则是显式地分配内存空间,在堆区生成新的对象实例[^1]。这意味着即使两个字符串具有相同的字符序列,只要一个是通过 `new` 关键字构建出来的,那么它们就不会共享同一个引用地址。 #### 3. **如何判断两个字符串是否相等?** 判断两个字符串的内容是否一致应当使用 `equals()` 方法而不是 `==` 操作符。后者仅用于比较两者的引用地址是否相同即是否指向同一块实际存在的数据区域。例如: ```java String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // true (因为s1和s2都指向字符串常量池中的"hello") String s3 = new String("hello"); System.out.println(s1.equals(s3)); // true (内容相同) System.out.println(s1 == s3); // false (不同对象) ``` #### 4. **什么是字符串驻留(Interning)?** 字符串驻留是指当 JVM 加载某个类时会将其中出现过的所有字符串文字放到一个特殊的内存区域——字符串常量池中去管理[^4]。对于任何新产生的字符串如果发现已有匹配项存在于该表之内则不再重复制造而是重用已有的那个副本。可以通过调用 `intern()` 来强制让某特定字符串进入这个优化结构当中。 #### 5. **replace() 函数有哪些重载形式及其作用分别是什么?** 存在两种主要形式的替换方法:一种是以单个字符为目标进行置换(`char oldChar, char newChar`);另一种允许更灵活地指定子串作为目标来进行整体替换成另一段文本 (`CharSequence target, CharSequence replacement`)[^3]。如下所示: ```java String originalStr = "Hello world!"; // 单字符替换 String resultSingleCharReplace = originalStr.replace('l', 'x'); // 输出:"Hexxo worxd!" // 整体字符串替换 String resultWholeWordReplace = originalStr.replace("world", "Java"); // 输出:"Hello Java!" ``` --- ### 总结 通过对这些经典问题的学习可以帮助求职者深入理解 Java 编程语言的核心概念之一 —— `String` 类型的工作机制及其背后涉及的一些重要理论依据如可变性、内存布局规划等方面的知识点[^2][^3][^4]。掌握这些问题不仅能提高个人技术水平还能增加面对技术筛选环节的信心水平。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值