【Java】String 全套高频面试题详解
大家好,我是程序员二叉。
简介
本文整理 Java 字符串模块经典面试考点,包含 == 与 equals、hashCode、toString、String 不可变特性、常量池、intern 方法、字符串拼接、String/ StringBuffer/ StringBuilder 区别等核心知识点,内容精简、直击考点,适合面试复习与日常学习。欢迎点赞收藏关注。
1. == 和 equals 有什么区别
- ==
基本数据类型:比较值是否相等
引用数据类型:比较内存地址是否相同 - equals()
默认:和 == 一样,比较对象地址
重写后:比较对象内容是否相等(如String、Integer)
2. 为什么重写hashCode就要重写equals
- 规范约定:equals相等的两个对象,hashCode必须相等
- 不重写会导致:HashMap/HashSet等集合无法正常工作
- 集合判断逻辑:先比较hashCode → 再比较equals → 决定是否视为同一对象
3. toString() 方法的作用是什么?为什么建议重写
- 作用:返回对象的字符串表示形式
- 默认:输出 类名@哈希值(无实际业务意义)
- 重写好处:打印对象时直接看到属性值,方便调试、日志输出
4. hashCode相同,equals一定为true吗?反过来呢
- hashCode相同 → equals不一定为true(哈希冲突)
- equals为true → hashCode一定相同(强制规范)
5. String的底层是怎么实现的
- JDK8及以前:char数组存储
private final char[] value - JDK9及以后:byte数组+编码标识
private final byte[] value节约内存
6. String为什么不可变?不可变优势是什么
不可变原因
- value数组被final修饰
- 类被final修饰,不能继承,无setter方法
- 所有修改操作都会返回新String对象
优势
- 线程安全,多线程无风险
- 字符串常量池复用,节约内存
- 哈希值可缓存,提升HashMap效率
- 安全(避免密码、token被篡改)
7. String s = new String(“abc”) 创建了几个对象
- 1个或2个
- 常量池无"abc":先创建常量池对象 → 再创建堆对象 →2个
- 常量池已有"abc":只创建堆对象 →1个
8. String s=“a”+“b”+“c” 创建了几个对象
- 编译器优化:直接合并为"abc"
- 常量池无则创建1个,有则0个 →最终1个或0个
9. +号拼接字符串的底层原理
- 变量拼接(如s1+s2):底层自动创建StringBuilder调用append()
- 常量拼接:编译器直接优化为完整字符串
- 循环中慎用+:会创建大量StringBuilder,效率低
10. String的hashCode()如何实现
publicinthashCode(){inth=hash;if(h==0&&value.length>0){for(bytev:value){h=31*h+v;}hash=h;}returnh;}公式:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
11. 如何比较字符串内容相等?为什么不能用 ==
- 正确方式:equals()
- == 比较地址,常量池复用可能地址相同,但非常量字符串地址不同
- 业务需求:比较内容,不是比较内存地址
12. 字符串常量池工作原理
- 存放编译期确定的字符串字面量
- 相同内容字符串共用一份,节约内存
- 位置:JDK7 + 移到堆内存
13. intern () 方法的作用
- 将字符串加入常量池
- 池中已存在:返回池中的对象引用
- 池中不存在:将当前字符串引用入池并返回
- 作用:大量重复字符串时节约内存
14. String、StringBuffer、StringBuilder 区别
| 类型 | 可变 | 线程安全 | 效率 |
|---|---|---|---|
| String | 不可变 | 安全 | 最低 |
| StringBuffer | 可变 | 安全(synchronized) | 中等 |
| StringBuilder | 可变 | 不安全 | 最高 |
使用场景
- 少量操作 / 常量:String
- 多线程大量拼接:StringBuffer
- 单线程大量拼接:StringBuilder(推荐)
总结(面试必背)
- == 比地址 / 值,equals 比内容(重写后)
- 重写 equals 必须重写 hashCode
- String 不可变 = final + 数组私有 + 无修改方法
- new String 可能创建 1~2 个对象,纯常量 + 编译器直接合并
- 字符串拼接优先 StringBuilder,循环禁止直接用 +
- 比较字符串内容必须用 equals
- 单线程首选 StringBuilder,多线程用 StringBuffer
