1. Java基础篇核心面试要点解析
1.1 OOP三大特性深度剖析
面向对象编程(OOP)是Java语言的基石,其三大特性在实际开发中无处不在。让我们深入理解这些特性的本质:
继承(Inheritance)的底层实现:
- JVM通过方法区存储类的继承关系信息
- 子类实例化时,会先调用父类构造器(隐式或显式)
- 方法调用时遵循"最近原则",通过虚方法表(vtable)实现动态绑定
封装(Encapsulation)的最佳实践:
- 使用private修饰字段,通过getter/setter控制访问
- 对setter方法添加参数校验逻辑
- 对复杂对象的构建使用Builder模式
- 示例:Spring框架中大量使用封装保护内部状态
多态(Polymorphism)的运行时机制:
- 方法重写(Override)实现运行时多态
- JVM通过invokevirtual指令实现动态分派
- 接口多态通过invokeinterface指令实现
- 实际应用:Spring IoC容器通过接口注入不同实现类
注意:滥用继承会导致"脆弱的基类"问题,优先考虑组合而非继承原则
1.2 方法重载与重写的本质区别
这两个概念看似简单,但在字节码层面有着根本差异:
重载(Overload):
- 编译时多态的体现
- 方法签名=方法名+参数类型列表
- 编译器根据静态类型选择方法版本
- 典型应用:构造器重载、工具类方法
重写(Override):
- 运行时多态的体现
- 需要满足"两同两小一大"规则:
- 方法名、参数列表相同
- 返回值类型和抛出异常小于等于父类
- 访问权限大于等于父类
- @Override注解可帮助编译器检查
字节码差异:
java复制// 重载示例
void test(int i) → invokestatic Test.test(I)V
void test(String s) → invokestatic Test.test(Ljava/lang/String;)V
// 重写示例
Parent p = new Child();
p.method() → invokevirtual Parent.method()V
// 实际执行Child.method()
1.3 接口与抽象类的工程化选择
在实际项目中如何选择?以下决策矩阵供参考:
| 考虑维度 | 选择接口场景 | 选择抽象类场景 |
|---|---|---|
| 默认实现 | 不需要 | 需要共享公共实现 |
| 状态管理 | 只能定义常量 | 可以定义实例变量 |
| 多继承需求 | 支持多继承 | 单继承限制 |
| 版本兼容 | 容易通过默认方法扩展 | 修改成本较高 |
| 模板方法模式 | 不适用 | 天然适用 |
Java 8+的接口增强:
- 默认方法(default method)解决接口演化问题
- 静态方法提供工具方法支持
- 函数式接口(@FunctionalInterface)支持Lambda
1.4 深拷贝与浅拷贝的实现方案
浅拷贝问题场景:
java复制class User implements Cloneable {
String name;
Address address; // 引用类型
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 默认浅拷贝
}
}
深拷贝实现方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 递归clone | 原生支持 | 需要处理循环引用 |
| 序列化 | 简单通用 | 性能较差 |
| 手动复制 | 完全可控 | 代码量大 |
| 工具类 | 使用方便 |
