最近正在复习Java八股,所以会将一些热门的八股问题,结合ai与自身理解写成博客便于记忆
本文将以以上问题作为基础
String 相关问题
String 底层数据类型?
String 在 Java 9 之前底层使用 char[]
数组存储字符数据,Java 9 及以后版本改为 byte[]
数组加上编码标志字段(coder),这样可以更节省内存空间(Latin1字符用1字节,UTF-16字符用2字节)。
String 类能被继承吗?
不能。String 类被声明为 final
,因此不能被继承。这样设计主要是为了保证 String 的不可变性和安全性。
String 是不可变的,如何实现?
String 的不可变性通过以下方式实现:
- 类声明为 final,防止被继承和修改
- 内部字符数组声明为 private final
- 不提供修改内部数组的方法
- 所有修改操作都返回新 String 对象而非修改原对象
String 存储有长度限制吗?
有长度限制:
- 理论最大长度受
Integer.MAX_VALUE
(2^31-1) 限制 - 实际限制更小,受 JVM 规范限制(常量池中 UTF-8 编码的字符串最大长度为 65535)
- 运行时创建字符串受 JVM 可用内存限制
为什么设计为不可变的?字符串常量池是什么?
不可变设计原因:
- 安全性:字符串常用于敏感信息(如密码、URL等),不可变防止被篡改
- 线程安全:无需同步即可在多线程中使用
- 缓存哈希值:String 是 HashMap 常用键,不可变保证哈希值不变
- 字符串常量池优化
字符串常量池:
- 是 JVM 中特殊的内存区域,用于存储字符串字面量
- 相同内容的字符串只存储一份,减少内存消耗
- 可通过
intern()
方法将字符串显式加入常量池
String/StringBuffer/StringBuilder的区别
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 是(天然) | 是(方法同步) | 否 |
性能 | 修改时性能差 | 较好 | 最好 |
使用场景 | 常量字符串 | 多线程字符串操作 | 单线程字符串操作 |
深拷贝与浅拷贝
什么是深拷贝和浅拷贝?
- 浅拷贝:只复制对象本身和其基本类型字段,引用类型字段仍指向原对象引用的对象
- 深拷贝:不仅复制对象本身,还递归复制其所有引用指向的对象
区别:
- 复制深度不同:浅拷贝只复制一层,深拷贝复制所有层级
- 内存消耗:深拷贝消耗更多内存
- 实现复杂度:深拷贝实现更复杂
- 独立性:深拷贝后的对象完全独立于原对象
异常处理
Error和Exception的区别
特性 | Error | Exception |
---|---|---|
类型 | 不可查异常(unchecked) | 可查异常(checked)和不可查异常 |
来源 | JVM 或系统底层问题 | 应用程序问题 |
处理方式 | 通常不捕获处理 | 应捕获处理 |
示例 | OutOfMemoryError | IOException |
异常的分类和区别
-
Checked Exception(检查型异常):
- 继承自 Exception
- 必须被捕获或声明抛出
- 代表可预期的异常情况
- 示例:IOException、SQLException
-
Unchecked Exception(非检查型异常):
- 继承自 RuntimeException
- 不强制捕获或声明
- 代表编程错误或系统问题
- 示例:NullPointerException、ArrayIndexOutOfBoundsException
finally中的代码一定会被执行吗?
大部分情况下会执行,但有几种特殊情况不会:
- 在 try 或 catch 块中调用
System.exit()
- 线程被中断或杀死
- JVM 崩溃
- 在 try 或 catch 块中进入无限循环
IO模型
AIO、BIO、NIO分别是什么
-
BIO(Blocking IO,阻塞IO):
- 同步阻塞模型
- 每个连接需要一个独立线程处理
- 简单但并发能力有限
-
NIO(Non-blocking IO,非阻塞IO):
- 同步非阻塞模型
- 基于通道(Channel)和缓冲区(Buffer)
- 使用选择器(Selector)实现多路复用
- 适合高并发场景
-
AIO(Asynchronous IO,异步IO):
- 异步非阻塞模型
- 基于事件和回调机制
- 操作系统完成IO操作后通知应用
- 性能最好但实现复杂
同步/异步与阻塞/非阻塞
同步与异步如何理解
- 同步:调用者主动等待调用结果(关注的是调用结果的通知方式)
- 异步:调用发出后立即返回,结果通过回调或通知机制告知(不阻塞调用者)
阻塞与非阻塞如何理解
- 阻塞:调用结果返回前,当前线程被挂起(关注的是调用等待期间线程的状态)
- 非阻塞:调用结果返回前,线程可以继续执行其他任务
组合模式:
- 同步阻塞(BIO)
- 同步非阻塞(NIO)
- 异步非阻塞(AIO)