各位晚上好,周一愉快(距离周五还有4天)
建议先看基础篇,再来看进阶篇。
系列介绍
欢迎来到"Java面试基础篇"系列!本系列旨在帮助Java开发者系统性地准备面试,每天精选至少5道经典面试题,涵盖Java基础、进阶、框架等各方面知识。坚持学习21天,助你面试通关!
基础面试题:
每日5题Java面试系列基础(1)
每日5题Java面试系列基础(2)
每日5题Java面试系列基础(3)
每日5题Java面试系列基础(4)
每日5题Java面试系列基础(5)
每日5题Java面试系列基础(6)
1. 如何理解 String 的 intern() 方法?
核心理解:
intern() 是 字符串驻留(String Interning) 的核心方法,用于将字符串对象手动加入 JVM 的字符串常量池(String Pool),并返回池中的唯一引用。
关键点与亮点:
- 内存优化:通过复用常量池中的字符串,减少重复对象的内存占用。
==与equals的差异:String s1 = new String("Hello"); String s2 = s1.intern(); System.out.println(s1 == s2); // false(堆对象 vs 常量池对象) System.out.println("Hello" == s2); // true(均指向常量池)- 性能权衡:
- 优点:适合大量重复字符串场景(如日志处理)。
- 缺点:驻留过程需哈希计算,可能引发常量池竞争(JDK 7+ 已将常量池移至堆中,缓解
PermGenOOM 问题)。
面试亮点:
提到 JDK 7 的常量池从
PermGen迁移到堆内存,结合-XX:StringTableSize调优(默认 60013,可扩容至百万级)。
2. Java 9 对 String 内部实现的改变及原因
改变内容:
- 存储结构:从
char[]改为byte[] + byte coder(标记编码类型)。 - 编码支持:
coder = 0:Latin-1(1 字节/字符)coder = 1:UTF-16(2 字节/字符)
设计动机:
- 内存节省:Latin-1 字符串(如纯英文)内存占用减少 50%。
- 性能提升:减少内存带宽压力,尤其适合大量短字符串场景(如 JSON 解析)。
代码验证:
String latin = "Hello"; // 内部使用 Latin-1 编码(1 字节/字符)
String emoji = "😊"; // 内部使用 UTF-16 编码(2 字节/字符)
面试亮点:
指出 Compact Strings 特性对微服务内存占用的实际影响(实测堆内存降低 10%~20%)。
3. 为什么需要 StringBuilder 和 StringBuffer?
核心原因:
- 不可变性的代价:
String的每次拼接(如+)会生成新对象,导致 O(n²) 时间复杂度。 - 可变字符序列:
StringBuilder:非线程安全,性能更高(单线程首选)。StringBuffer:线程安全(方法加synchronized),适合多线程拼接。
性能对比:
// ❌ 低效(生成多个中间对象)
String result = "";
for (int i = 0; i < 10000; i++) {
result += i;
}
// ✅ 高效(原地修改)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
面试亮点:
提到 JVM 对
+的优化:编译期常量折叠(如"a" + "b"变为"ab"),但循环内拼接仍需手动优化。
4. 不可变对象的设计模式适用场景
核心优势:
- 线程安全:无需同步(如
String、BigDecimal)。 - 缓存友好:哈希值、计算结果可缓存(如
Pattern的编译正则)。 - 防御性编程:防止被篡改(如数据库连接参数)。
经典场景:
- 值对象:货币、日期、坐标(
record类型在 JDK 14+ 强化了不可变性)。 - 并发共享数据:
ConcurrentHashMap的Key必须不可变。 - 函数式编程:Lambda 表达式捕获的变量需为
final或等效不可变。
面试亮点:
对比 享元模式(Flyweight):
String常量池是享元模式的典型实现。
5. Java 中处理不同编码的字符串
关键 API:
- 编码:
String.getBytes(Charset.forName("GBK")) - 解码:
new String(byte[], "UTF-8")
最佳实践:
- 显式指定编码:避免依赖平台默认编码(如
new InputStreamReader(is, StandardCharsets.UTF_8))。 - 通用方案:
// 读取文件时指定编码 Files.readAllLines(Paths.get("file.txt"), Charset.forName("GB18030"));
面试亮点:
强调
StandardCharsets常量类(JDK 7+)优于字符串硬编码(避免拼写错误)。
6. 浏览器乱码问题解决方案
常见原因:
- 服务端与浏览器编码不一致(如服务端返回 GBK,浏览器解析为 UTF-8)。
- HTTP 头缺失:未设置
Content-Type: text/html;charset=UTF-8。
解决步骤:
- 统一编码:全栈使用 UTF-8(数据库、后端、前端)。
- HTTP 头显式声明:
response.setContentType("text/html;charset=UTF-8"); // Java Web - HTML Meta 标签(双保险):
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
面试亮点:
提到 BOM 问题:UTF-8 文件开头的 BOM 可能导致某些浏览器解析异常(如
乱码)。
7. 为什么 UTF-8 成为互联网主流编码?
核心优势:
- 兼容性:ASCII 字符仍占 1 字节(英文场景高效)。
- 变长编码:节省空间(中文通常 3 字节,而 UTF-16 固定 2/4 字节)。
- 无字节序问题:无需 BOM(与 UTF-16/UTF-32 不同)。
- 自同步性:可从任意字节恢复字符边界(鲁棒性强)。
数据支持:
W3Techs 统计显示:98% 的网站使用 UTF-8(2023 年数据)。
8. BOM(字节顺序标记)的作用与争议
定义:
- BOM(Byte Order Mark):
U+FEFF字符,用于标记文本的字节序(大端/小端)和编码类型。
常见场景:
- UTF-16/UTF-32:必须用 BOM 标识字节序(如
FE FF表示大端)。 - UTF-8:不建议使用 BOM(RFC 3629 规定 UTF-8 无字节序问题)。
问题案例:
- Java 文件编译错误:UTF-8 with BOM 可能导致
package语句解析失败。 - Linux 脚本执行异常:Shebang(
#!/bin/bash)前出现 BOM 会报错。
面试亮点:
指出 Maven/Gradle 构建工具会过滤 BOM,但 IDE(如 Notepad)可能自动添加。
22万+

被折叠的 条评论
为什么被折叠?



