【Java 基础】核心知识点梳理
Java 基础核心知识点梳理
一、Java 核心特性
Java 之所以成为后端开发的主流语言,核心源于其四大核心特性,也是面试高频考点:
1. 平台无关性(跨平台)
- 核心原理:Java 源代码(.java)经编译器(javac)编译为字节码(.class),字节码不依赖具体操作系统,仅需运行在安装了 Java 虚拟机(JVM)的环境中,由 JVM 将字节码解释 / 编译为机器码执行。
- 关键优势:一次编译,多处运行,解决了传统语言(如 C++)需针对不同系统重新编译的问题。
- 注意:跨平台的是字节码,而非 JVM 本身 ——JVM 需针对 Windows、Linux、Mac 等系统单独实现。
2. 面向对象(OOP)
- 核心思想:将现实世界的事物抽象为 “对象”,对象包含 “属性”(数据)和 “行为”(方法),以对象为中心组织代码,提高复用性和可维护性。
- 三大核心特性:封装、继承、多态(详情见下文)。
- 关键说明:Java 是 “几乎纯面向对象” 的语言,仅基本数据类型(int、long 等)不是对象,其余皆为对象或对象的引用。
3. 自动内存管理(垃圾回收 GC)
- 核心作用:JVM 自动管理对象的内存分配与回收,无需开发者手动调用
free()
或delete
释放内存,减少内存泄漏风险。 - 核心原理:通过垃圾回收器(如 G1、ZGC)识别 “不再被引用的对象”,并在合适时机释放其占用的内存。
- 注意:GC 并非实时执行,开发者可通过
System.gc()
建议 JVM 执行 GC,但无法强制。
4. 其他重要特性
- 安全性:自带安全管理器,限制恶意代码的权限(如文件读写、网络访问);
- 多线程支持:内置
Thread
类、synchronized
关键字等,简化多线程编程; - 丰富的类库:提供 java.lang、java.util、java.io 等核心类库,覆盖数据结构、IO、网络等常见场景。
二、JDK、JRE、JVM 的关系
三者是 Java 开发 / 运行的核心环境,需明确区分其职责与包含关系:
组件 | 中文名称 | 核心组成 | 核心用途 |
---|---|---|---|
JDK | Java 开发工具包 | JRE + 开发工具(javac 编译器、javadoc 文档生成器、jdb 调试器等) | Java 程序的开发、编译、测试、运行 |
JRE | Java 运行时环境 | JVM + 核心类库(java.lang、java.util 等) | 仅支持 Java 程序的运行(无开发工具) |
JVM | Java 虚拟机 | 内存管理模块、垃圾回收模块、字节码执行引擎等 | 将字节码转换为机器码并执行,是跨平台的核心 |
核心关系:JDK ⊇ JRE ⊇ JVM
- 开发时需安装 JDK(需编译代码);
- 仅运行 Java 程序时,安装 JRE 即可;
- JVM 是跨平台的核心,但无法单独工作,依赖 JRE 提供的类库支持。
三、基本数据类型与类型转换
1. 基本数据类型(8 种)
类型 | 占用字节 | 范围 | 默认值 |
---|---|---|---|
byte | 1 | -128 ~ 127 | 0 |
short | 2 | -32768 ~ 32767 | 0 |
int | 4 | -2³¹ ~ 2³¹-1 | 0 |
long | 8 | -2⁶³ ~ 2⁶³-1 | 0L |
float | 4 | 单精度浮点数 | 0.0f |
double | 8 | 双精度浮点数 | 0.0d |
char | 2 | ‘\u0000’ ~ ‘\uffff’(Unicode 字符) | ‘\u0000’ |
boolean | 1 | true/false | false |
2. long 与 int 的互转
-
int → long(向上转型):安全无数据丢失,支持直接赋值或显式强制转换。
int num = 100; long longNum1 = num; // 直接赋值(推荐) long longNum2 = (long) num; // 显式转换(冗余但合法)
-
long → int(向下转型):可能溢出(long 范围远大于 int),必须显式强制转换,需手动确保数据在 int 范围内。
long longNum = 200L; int num = (int) longNum; // 合法(200在int范围内)long bigNum = 2147483648L; // 超过int最大值(2147483647) int errorNum = (int) bigNum; // 溢出,结果为负数(不可预期)
四、面向对象核心(三大特性 + 设计原则)
1. 三大核心特性
(1)封装
-
定义:将对象的属性(成员变量)和行为(方法)封装为一个整体,通过
private
修饰属性隐藏内部细节,仅提供public
的 getter/setter 方法与外界交互。 -
核心优势:提高代码安全性(防止属性被随意修改)、简化编程(外界无需关注内部实现)。
-
示例:
public class User {private String name; // 私有属性(隐藏细节)// 提供公共接口与外界交互public String getName() {return name;}public void setName(String name) {// 可添加校验逻辑(如非空),增强安全性if (name != null && !name.isEmpty()) {this.name = name;}}
(2)继承
-
定义:子类(SubClass)继承父类(SuperClass)的属性和方法,同时可扩展自身的属性和方法,是代码复用的核心手段。
-
关键规则:
- Java 单继承(一个子类只能有一个直接父类),但支持多层继承;
- 子类通过
extends
关键字继承父类,通过super
关键字调用父类的构造方法、属性或方法; - 父类的
private
成员子类无法直接访问,需通过父类提供的公共方法间接访问。
-
示例:
public class Animal { // 父类public void eat() {System.out.println("动物进食");} }public class Dog extends Animal { // 子类继承父类@Overridepublic void eat() { // 重写父类方法super.eat(); // 调用父类方法System.out.println("狗吃骨头");} }
(3)多态
- 定义:同一接口(或父类)的不同实现类,对同一消息作出不同响应。
- 两种实现形式:
- 编译时多态(重载 Overload):同一类中,方法名相同、参数列表(类型 / 个数 / 顺序)不同,返回值可不同,编译时确定调用哪个方法;
- 运行时多态(重写 Override):子类重写父类的方法(方法名、参数列表、返回值完全一致),运行时 JVM 根据对象的实际类型调用对应方法。
- 多态的前提:继承关系、方法重写、父类引用指向子类对象(
Animal dog = new Dog();
)。
2. 面向对象六大设计原则
原则 | 核心思想 | 通俗理解 | 示例 |
---|---|---|---|
单一职责原则(SRP) | 一个类只负责一项职责 | 一个类只做一件事,避免 “万能类” | 员工类仅管理员工信息,不负责薪资计算(薪资计算单独写薪资类) |
开放封闭原则(OCP) | 对扩展开放,对修改封闭 | 新增功能通过扩展实现,不修改原有代码 | 新增图形类型(圆形→三角形),只需新增三角形类继承图形接口,不修改图形接口本身 |
里氏替换原则(LSP) | 子类可替换父类,不影响程序正确性 | 子类不能破坏父类的行为约定 | 正方形不能继承矩形(修改矩形的宽高时,正方形的边长逻辑会冲突) |
接口隔离原则(ISP) | 接口应小而专,不依赖无用接口 | 避免 “臃肿接口”,按需暴露方法 | 无需让 “学生” 接口继承 “支付” 接口(学生未必需要支付功能) |
依赖倒置原则(DIP) | 依赖抽象,不依赖具体实现 | 高层模块和低层模块都依赖接口 / 抽象类 | 公司类依赖 “部门接口”,而非具体的 “技术部门” 类(可灵活替换为 “运营部门”) |
最少知识原则(LOD) | 一个对象仅与直接关联的对象交互 | 减少对象间的耦合,不依赖 “间接对象” | 学生只需与班主任交互,无需直接与校长交互(通过班主任转达) |
五、关键字核心用法(final、static 等)
1. final 关键字
final 用于限制 “不可变”,可修饰类、方法、变量,核心用法如下:
修饰对象 | 核心作用 | 注意事项 |
---|---|---|
类 | 该类不能被继承 | 如String 类(保证不可变性和安全性) |
方法 | 该方法不能被子类重写 | 如Object.getClass() 方法(避免子类修改对象类型判断逻辑) |
基本类型变量 | 变量值不能重新赋值 | final int num = 10; num = 20; // 编译错误 |
引用类型变量 | 引用不能指向新对象,但对象内容可修改 | final User user = new User(); user.setName("李四"); // 合法;user = new User(); // 编译错误 |
2. static 关键字(补充)
- 修饰变量:静态变量(类变量),属于类本身,所有对象共享,随类加载而初始化(仅初始化一次);
- 修饰方法:静态方法,属于类,可直接通过 “类名。方法名” 调用,不能访问非静态成员(无 this 指针);
- 修饰代码块:静态代码块,类加载时执行,用于初始化静态变量,仅执行一次。
六、对象拷贝(浅拷贝 vs 深拷贝)
1. 核心区别
类型 | 定义 | 特点 |
---|---|---|
浅拷贝 | 仅拷贝对象本身,对象的属性(引用类型)仍指向原对象的引用 | 拷贝效率高,可能导致 “修改拷贝对象的属性,原对象属性也变化” |
深拷贝 | 拷贝对象本身及所有引用类型属性,形成完全独立的新对象 | 拷贝后两个对象完全独立,无关联,但效率较低 |
2. 实现方式
-
浅拷贝:实现
Cloneable
接口,重写
clone()
方法(默认是浅拷贝);
public class User implements Cloneable {private String name;private Address address; // 引用类型@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 浅拷贝,address仍指向原对象} }
-
深拷贝:
- 递归实现
Cloneable
接口(对每个引用类型属性也进行拷贝); - 通过序列化(如 Jackson)将对象转为字节流,再反序列化为新对象(推荐,无需手动递归)。
- 递归实现
七、反射机制
1. 核心定义
反射是 Java 的动态特性,允许程序在运行时:
- 获取任意类的完整结构(类名、属性、方法、构造函数、注解等);
- 动态创建对象实例;
- 动态调用对象的方法(包括私有方法);
- 动态修改对象的属性(包括私有属性)。
2. 核心 API(基于java.lang.reflect
包)
类名 | 核心作用 |
---|---|
Class | 代表类的字节码对象,是反射的入口(通过Class.forName() 、对象.getClass() 、类名.class 获取) |
Field | 代表类的属性,用于获取 / 修改属性值 |
Method | 代表类的方法,用于动态调用方法 |
Constructor | 代表类的构造函数,用于动态创建对象 |
3. 典型应用场景
- 加载数据库驱动:
Class.forName("com.mysql.cj.jdbc.Driver")
(通过反射加载驱动类,注册到 JDBC); - 框架核心:Spring IOC(通过配置文件动态加载 Bean,依赖反射创建对象)、MyBatis(通过反射映射数据库字段与 Java 对象属性);
- 配置文件解析:如读取 XML 配置的类名,动态创建实例。
4. 优缺点
- 优点:灵活性高,降低代码耦合(如框架无需硬编码依赖具体类);
- 缺点:性能略低(反射需动态解析字节码)、破坏封装性(可访问私有成员)。
八、注解(Annotation)
1. 核心原理
- 注解本质是继承了
java.lang.annotation.Annotation
的特殊接口,其具体实现类是 JVM 运行时生成的动态代理类; - 反射获取注解时,返回的是动态代理对象,调用注解的方法时,最终通过
AnnotationInvocationHandler.invoke()
方法从memberValues
(存储注解属性的 Map)中获取值。
2. 核心分类(按作用域:RetentionPolicy
)
作用域 | 核心特点 | 应用场景 |
---|---|---|
SOURCE | 仅保留在源码中,编译为字节码时删除 | 语法检查(如@Override 、@SuppressWarnings ) |
CLASS | 保留到字节码中,运行时不加载到 JVM | 字节码增强(如 Lombok 注解) |
RUNTIME | 保留到运行时,可通过反射获取 | 框架注解(如 Spring@Autowired 、MyBatis@Select ) |
3. 关键说明
- 注解本身不具备业务逻辑,需通过 “注解解析器”(反射 + 逻辑处理)实现功能;
- 仅
RUNTIME
级别的注解能通过反射解析,是开发中最常用的类型。
九、异常体系
1. 体系结构
Java 异常体系的根类是Throwable
,其下分为两大子类:
Throwable
├─ Error(错误):JVM运行时的严重错误,程序无法处理,如OutOfMemoryError(内存溢出)、StackOverflowError(栈溢出)
└─ Exception(异常):程序可处理的异常,分为两类├─ 受检异常(编译时异常):编译时必须捕获或声明抛出,如FileNotFoundException(文件不存在)、SQLException(数据库异常)└─ 非受检异常(运行时异常):继承自`RuntimeException`,编译时无需强制处理,由程序逻辑错误导致,如NullPointerException(空指针)、ArrayIndexOutOfBoundsException(数组越界)、IllegalArgumentException(参数非法)
2. 异常处理方式
(1)主动抛出异常
throw
:在方法内部手动抛出异常对象(如throw new NullPointerException("参数不能为空")
);throws
:在方法声明上声明该方法可能抛出的异常类型,将异常交给调用者处理(如public void readFile() throws FileNotFoundException
)。
(2)捕获处理异常(try-catch-finally)
- 执行顺序:
- 无异常:try → finally;
- 有异常:try → 匹配的 catch → finally;
- 核心注意:
- finally 块必定执行(除非 JVM 退出,如
System.exit(0)
),常用于释放资源(关闭文件、数据库连接); - catch 块可多个,需按 “异常子类→父类” 的顺序排列(否则编译错误)。
- finally 块必定执行(除非 JVM 退出,如
(3)自定义异常
继承Exception
(受检异常)或RuntimeException
(非受检异常),用于业务特定异常场景(如UserNotFoundException
)。
十、集合遍历与迭代器
1. 集合遍历方式
遍历方式 | 适用场景 | 核心特点 |
---|---|---|
迭代器(Iterator) | 所有实现Iterable 接口的集合(List、Set、Map 的 entrySet 等) | 支持在遍历中安全删除元素(iterator.remove() ) |
增强 for 循环(forEach) | 仅遍历元素,无需修改集合 | 底层依赖迭代器,代码简洁(for (String s : list) {} ) |
Lambda 表达式(Stream) | 集合数据过滤、映射等复杂处理 | 支持并行处理,代码简洁(list.stream().filter(s -> s.length() > 3).collect(Collectors.toList()) ) |
普通 for 循环(索引) | List 集合(有索引) | 可通过索引修改元素,支持逆序遍历 |
2. 迭代器(Iterator)核心
- 核心思想:提供统一的遍历接口,屏蔽不同集合(数组、链表、哈希表)的底层数据结构差异,符合 “迭代器设计模式”;
- 核心方法:
hasNext()
:判断是否还有下一个元素;next()
:获取下一个元素(注意:需先调用hasNext()
,否则抛出NoSuchElementException
);remove()
:删除当前遍历的元素(需在next()
之后调用,且只能调用一次);
- 实现原理:每个集合类(如 ArrayList、LinkedList)通过内部类实现
Iterator
接口,结合自身数据结构定制遍历逻辑(如 ArrayList 用索引,LinkedList 用指针)。
十一、动态代理
动态代理是 “不修改目标类代码,增强目标类方法” 的核心技术,常用于框架(如 Spring AOP)。
1. 两种实现方式对比
特性 | JDK 动态代理 | Cglib 动态代理 |
---|---|---|
核心原理 | 生成目标类所实现接口的代理类 | 生成目标类的子类(通过 ASM 字节码框架) |
依赖条件 | 目标类必须实现接口 | 目标类不能是 final 类(否则无法继承) |
方法增强 | 仅增强接口中声明的方法 | 增强目标类的所有非 final 方法 |
性能 | JDK8 + 后性能接近 Cglib | 早期性能优于 JDK,JDK 升级后差距缩小 |
核心 API | java.lang.reflect.Proxy 、InvocationHandler | Cglib 的Enhancer 、MethodInterceptor |
2. 核心作用
- 方法增强:在目标方法执行前后添加逻辑(如日志记录、权限校验、事务管理);
- 解耦:增强逻辑与目标类分离,无需修改目标类代码。
十二、Java 8 核心新特性
Java 8 是里程碑式版本,新增特性极大简化了代码,面试高频:
新特性 | 核心作用 | 示例 |
---|---|---|
Lambda 表达式 | 简化匿名内部类,支持函数式编程 | List<Integer> list = Arrays.asList(1,2,3); list.forEach(n -> System.out.println(n)); |
Stream API | 集合数据的声明式处理(过滤、映射、聚合) | list.stream().filter(n -> n % 2 == 0).sum(); // 求和偶数 |
函数式接口 | 仅含一个抽象方法的接口(@FunctionalInterface 标记) | Consumer<String> consumer = s -> System.out.println(s); |
Optional 类 | 优雅处理空指针(避免NullPointerException ) | Optional.ofNullable(user).map(User::getName).orElse("默认名称"); |
方法引用 | 简化 Lambda 表达式(复用已有方法) | list.forEach(System.out::println); // 等价于s -> System.out.println(s) |
十三、序列化与反序列化
1. 核心目的
解决 “内存中对象的瞬时性” 与 “数据持久化 / 跨域传输” 的矛盾:
- 持久化:将对象保存到文件、数据库等(如用户登录状态序列化到本地);
- 跨域传输:在网络中传输对象(如微服务间通过 JSON 传输数据)。
2. 实现方式
(1)Java 原生序列化
- 核心要求:目标类实现
java.io.Serializable
接口(标记接口,无抽象方法); - 核心 API:
ObjectOutputStream
(序列化,writeObject()
)、ObjectInputStream
(反序列化,readObject()
); - 关键注意:
- 需显式声明
serialVersionUID
(序列化版本号),避免类结构修改后反序列化失败; - 缺点:仅支持 Java 语言,序列化后为二进制字节流,可读性差。
- 需显式声明
(2)JSON 序列化(现代开发首选)
-
核心工具:Jackson、FastJSON 等框架;
-
核心优势:跨语言(Java、Python、Go 等均可解析)、可读性强(文本格式)、无需实现接口;
-
示例(Jackson):
ObjectMapper mapper = new ObjectMapper(); User user = new User("张三", 25); String json = mapper.writeValueAsString(user); // 序列化(对象→JSON字符串) User user2 = mapper.readValue(json, User.class); // 反序列化(JSON→对象)
3. 序列化的注意事项
- transient 关键字:修饰的属性不会被序列化(如密码字段);
- 静态变量:不会被序列化(属于类,而非对象);
- 循环引用:需通过注解(如 Jackson 的
@JsonIgnore
)避免序列化死循环。