1. Java面向对象编程基础概念
面向对象编程(OOP)是Java语言的核心思想,也是现代软件开发的主流范式。与面向过程编程相比,OOP更贴近现实世界的思维方式。在Java中,一切皆对象,而类则是创建对象的蓝图。
提示:Java SE(Standard Edition)是Java平台的标准版,包含了开发桌面和简单服务器应用所需的核心API和JVM。
面向对象的三大基本特性:
- 封装:隐藏对象内部细节,通过公共方法访问数据
- 继承:子类可以继承父类的属性和方法
- 多态:同一操作作用于不同对象会产生不同行为
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 类的定义与基本语法
2.1 类的基本结构
一个最简单的Java类定义如下:
java复制[访问修饰符] class 类名 {
// 成员变量(属性)
[访问修饰符] 数据类型 变量名;
// 构造方法
[访问修饰符] 类名(参数列表) {
// 初始化代码
}
// 成员方法
[访问修饰符] 返回值类型 方法名(参数列表) {
// 方法体
}
}
2.2 类的主要组成部分详解
2.2.1 访问修饰符
Java提供了四种访问级别:
- public:对所有类可见
- protected:对同一包内的类和所有子类可见
- 默认(不写修饰符):仅对同一包内的类可见
- private:仅对本类可见
注意:一个Java源文件中只能有一个public类,且文件名必须与public类名相同。
2.2.2 成员变量
成员变量也称为属性或字段,用于描述对象的特征。定义时应考虑:
- 数据类型:基本类型或引用类型
- 命名规范:小驼峰命名法(如studentName)
- 初始化:可以在声明时初始化,也可以在构造方法中初始化
2.2.3 构造方法
构造方法特点:
- 方法名与类名相同
- 没有返回类型(连void都没有)
- 可以重载(多个不同参数的构造方法)
- 如果没有显式定义,编译器会自动提供默认无参构造方法
2.2.4 成员方法
成员方法定义对象的操作行为,包含:
- 方法签名:方法名+参数列表
- 方法体:具体的实现代码
- 返回值:使用return语句返回,void表示无返回值
3. 类的使用与对象创建
3.1 创建对象的基本步骤
java复制// 1. 声明对象引用
ClassName objectName;
// 2. 实例化对象
objectName = new ClassName();
// 也可以合并为一步
ClassName objectName = new ClassName();
3.2 对象的内存模型
Java对象在内存中的存储分为三部分:
- 对象头:存储对象的元数据(如哈希码、GC信息等)
- 实例数据:存储对象的属性值
- 对齐填充:确保对象大小是8字节的整数倍
提示:使用new关键字创建对象时,JVM会在堆内存中分配空间,对象引用变量存储在栈内存中。
3.3 对象初始化的完整过程
- 加载类:如果类尚未加载,JVM会加载.class文件
- 分配内存:在堆中为新对象分配内存空间
- 默认初始化:为成员变量赋默认值(数值为0,布尔为false,引用为null)
- 显式初始化:执行成员变量的显式初始化(如果有)
- 构造代码块:执行类中的构造代码块
- 构造方法:执行对应的构造方法
4. 类的进阶特性
4.1 static关键字
static修饰的成员属于类而非对象:
- 静态变量:所有对象共享同一份数据
- 静态方法:只能访问静态成员,不能使用this
- 静态代码块:类加载时执行,用于初始化静态资源
java复制class MyClass {
static int count = 0; // 静态变量
static {
// 静态代码块
System.out.println("类被加载了");
}
static void printCount() { // 静态方法
System.out.println("Count: " + count);
}
}
4.2 final关键字
final可以修饰:
- 类:表示不可被继承
- 方法:表示不可被重写
- 变量:表示常量,只能赋值一次
java复制final class FinalClass { // 不可继承的类
final int MAX_VALUE = 100; // 常量
final void finalMethod() { // 不可重写的方法
// 方法实现
}
}
4.3 this关键字
this表示当前对象的引用,主要用途:
- 区分成员变量和局部变量
- 在构造方法中调用其他构造方法(必须放在第一行)
- 作为参数传递当前对象
java复制class Person {
String name;
Person(String name) {
this.name = name; // 区分成员变量和参数
}
Person() {
this("Unknown"); // 调用其他构造方法
}
}
5. 类的设计原则与最佳实践
5.1 单一职责原则
一个类应该只有一个引起它变化的原因。这意味着:
- 每个类只负责一项明确的职责
- 避免创建"万能类"
- 将大类拆分为多个小类
5.2 封装性原则
良好的封装应该:
- 将成员变量设为private
- 提供public的getter和setter方法
- 在方法中进行必要的参数校验
java复制public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
if(name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("姓名不能为空");
}
this.name = name;
}
// 其他getter和setter
}
5.3 不可变类设计
不可变类的特点:
- 所有成员变量设为private final
- 不提供setter方法
- 类本身声明为final
- 如果包含可变对象的引用,需要进行防御性拷贝
java复制public final class ImmutablePoint {
private final int x;
private final int y;
public ImmutablePoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
}
6. 常见问题与解决方案
6.1 对象创建失败的可能原因
- 类路径问题:确保类在classpath中
- 构造方法异常:检查构造方法中的代码
- 内存不足:JVM堆内存不足时抛出OutOfMemoryError
- 类未加载:检查类加载机制
6.2 空指针异常预防
空指针异常(NullPointerException)是最常见的运行时异常,预防措施:
- 对象使用前进行null检查
- 使用Optional类处理可能为null的情况
- 合理设计方法,避免返回null
- 使用Objects.requireNonNull进行参数校验
6.3 循环依赖问题
当两个类相互引用时可能导致问题,解决方案:
- 重新设计类关系,消除循环依赖
- 使用接口解耦
- 延迟初始化(懒加载)
java复制class A {
private B b;
public void setB(B b) { // 通过setter注入
this.b = b;
}
}
class B {
private A a;
public void setA(A a) {
this.a = a;
}
}
7. 实际应用案例
7.1 学生管理系统中的类设计
java复制public class Student {
private String id;
private String name;
private int age;
private List<Course> courses;
// 构造方法、getter和setter
public void addCourse(Course course) {
if(courses == null) {
courses = new ArrayList<>();
}
courses.add(course);
}
}
public class Course {
private String courseId;
private String courseName;
private int credit;
// 构造方法、getter和setter
}
public class StudentManagementSystem {
private Map<String, Student> students;
public void addStudent(Student student) {
students.put(student.getId(), student);
}
// 其他管理方法
}
7.2 银行账户系统实现
java复制public class BankAccount {
private final String accountNumber;
private double balance;
private final String owner;
private final Date createDate;
public BankAccount(String accountNumber, String owner) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = 0.0;
this.createDate = new Date();
}
public void deposit(double amount) {
if(amount <= 0) {
throw new IllegalArgumentException("存款金额必须大于0");
}
balance += amount;
}
public void withdraw(double amount) {
if(amount <= 0) {
throw new IllegalArgumentException("取款金额必须大于0");
}
if(amount > balance) {
throw new IllegalStateException("余额不足");
}
balance -= amount;
}
// 其他方法...
}
8. 性能优化与高级技巧
8.1 对象池技术
对于创建成本高的对象,可以使用对象池:
- 预先创建一组对象并保存在池中
- 需要时从池中获取
- 使用完毕后归还池中
java复制public class ObjectPool<T> {
private Queue<T> pool;
private Supplier<T> creator;
public ObjectPool(int size, Supplier<T> creator) {
this.creator = creator;
pool = new LinkedList<>();
for(int i = 0; i < size; i++) {
pool.add(creator.get());
}
}
public T borrow() {
return pool.isEmpty() ? creator.get() : pool.poll();
}
public void returnToPool(T obj) {
pool.offer(obj);
}
}
8.2 延迟初始化
对于不一定会使用的资源,可以采用延迟初始化:
- 使用volatile保证可见性
- 双重检查锁定保证线程安全
java复制public class LazyInit {
private volatile ExpensiveObject instance;
public ExpensiveObject getInstance() {
if(instance == null) {
synchronized(this) {
if(instance == null) {
instance = new ExpensiveObject();
}
}
}
return instance;
}
}
8.3 不可变对象优化
不可变对象的优势:
- 线程安全,无需同步
- 可以缓存和重用
- 适合作为Map的键
java复制public final class OptimizedString {
private final char[] value;
private int hash; // 缓存哈希值
public OptimizedString(char[] value) {
this.value = Arrays.copyOf(value, value.length);
}
@Override
public int hashCode() {
int h = hash;
if(h == 0 && value.length > 0) {
for(char c : value) {
h = 31 * h + c;
}
hash = h;
}
return h;
}
}
9. 现代Java中的类特性
9.1 Record类(Java 14+)
Record是特殊的不可变类:
- 自动生成final字段、构造方法、equals/hashCode/toString
- 适合作为数据载体
java复制public record Point(int x, int y) {
// 编译器会自动生成:
// private final int x;
// private final int y;
// 构造方法
// getter方法(x()和y())
// equals/hashCode/toString
}
9.2 Sealed类(Java 17+)
Sealed类限制可以继承它的子类:
- 使用permits子句指定允许的子类
- 子类必须直接继承且为final、sealed或non-sealed
java复制public sealed class Shape permits Circle, Rectangle, Triangle {
// 公共方法
}
public final class Circle extends Shape {
private double radius;
// 实现细节
}
public non-sealed class Rectangle extends Shape {
private double width, height;
// 实现细节
}
9.3 模式匹配(Java 16+)
简化类型检查和转换:
java复制if(obj instanceof String s) {
// 可以直接使用s
System.out.println(s.length());
}
// switch表达式中的模式匹配
return switch(shape) {
case Circle c -> "圆形,半径: " + c.radius();
case Rectangle r -> "矩形,面积: " + (r.width() * r.height());
default -> "未知形状";
};
10. 类与JVM的关系
10.1 类加载机制
JVM加载类的过程:
- 加载:查找并加载.class文件
- 验证:确保类文件格式正确
- 准备:为静态变量分配内存并设置默认值
- 解析:将符号引用转换为直接引用
- 初始化:执行静态代码块和静态变量赋值
10.2 类加载器层次结构
Java类加载器分为:
- 启动类加载器(Bootstrap ClassLoader):加载核心Java类
- 扩展类加载器(Extension ClassLoader):加载扩展库
- 系统类加载器(Application ClassLoader):加载应用类路径下的类
- 自定义类加载器:用户定义的类加载器
10.3 类的生命周期
一个类在JVM中的生命周期包括:
- 加载(Loading)
- 链接(Linking):验证、准备、解析
- 初始化(Initialization)
- 使用(Using)
- 卸载(Unloading)
11. 设计模式中的类应用
11.1 工厂模式
通过工厂类创建对象,隐藏具体实现:
java复制public interface Product {
void use();
}
public class ConcreteProduct implements Product {
public void use() {
System.out.println("使用具体产品");
}
}
public class ProductFactory {
public static Product createProduct() {
return new ConcreteProduct();
}
}
11.2 单例模式
确保一个类只有一个实例:
java复制public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
11.3 观察者模式
定义对象间的一对多依赖关系:
java复制public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("收到消息: " + message);
}
}
public class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for(Observer observer : observers) {
observer.update(message);
}
}
}
12. 测试与调试技巧
12.1 单元测试最佳实践
针对类的单元测试应该:
- 每个测试方法只测试一个功能
- 使用有意义的测试方法名
- 包含边界条件测试
- 使用断言验证结果
java复制public class CalculatorTest {
@Test
public void testAdd_PositiveNumbers_ReturnsCorrectSum() {
Calculator calc = new Calculator();
assertEquals(5, calc.add(2, 3));
}
@Test
public void testAdd_NegativeNumbers_ReturnsCorrectSum() {
Calculator calc = new Calculator();
assertEquals(-1, calc.add(2, -3));
}
}
12.2 调试技巧
有效的类调试方法:
- 使用IDE的调试功能设置断点
- 检查对象状态和变量值
- 使用日志记录重要信息
- 使用条件断点过滤无关情况
12.3 性能分析工具
分析类性能的常用工具:
- JVisualVM:监控内存和CPU使用
- JProfiler:分析内存泄漏和性能瓶颈
- YourKit:全面的性能分析工具
- Java Mission Control:JDK自带的监控工具
13. 代码质量与重构
13.1 代码异味识别
类设计中常见的代码异味:
- 过大的类(God Class)
- 过长的参数列表
- 过多的基本类型使用
- 数据类(只有getter/setter)
- 过度耦合的类
13.2 重构技巧
改善类设计的重构方法:
- 提取方法:将长方法拆分为小方法
- 提取类:将大类拆分为多个小类
- 引入参数对象:减少方法参数数量
- 用多态替代条件语句
- 引入Null对象替代null检查
13.3 代码度量指标
评估类质量的常用指标:
- 圈复杂度:衡量方法的复杂度
- 继承深度:类的继承层次
- 类耦合度:与其他类的依赖关系
- 方法数:类中包含的方法数量
- 代码行数:类的规模大小
14. 工具与框架支持
14.1 IDE功能
现代IDE提供的类相关功能:
- 类图生成:可视化类结构
- 代码导航:快速跳转到类定义
- 重构工具:安全地修改类结构
- 代码模板:快速生成常用代码结构
- 代码分析:识别潜在问题
14.2 构建工具
管理类依赖的构建工具:
- Maven:基于POM的项目管理
- Gradle:灵活的构建自动化
- Ant:传统的Java构建工具
14.3 文档生成
为类生成文档的工具:
- Javadoc:标准的Java文档工具
- Doxygen:支持多种语言的文档生成
- Swagger:REST API文档生成
15. 未来发展趋势
15.1 模块化(Java 9+)
Java模块系统(JPMS)特性:
- 更强的封装性
- 显式模块依赖
- 改善的可维护性
- 更小的运行时镜像
15.2 值类型(未来可能)
值类型(Value Types)提案:
- 类似基本类型的语义
- 不可变性
- 无对象头开销
- 更好的内存局部性
15.3 协程与轻量级线程
Project Loom带来的变化:
- 虚拟线程(轻量级线程)
- 结构化并发
- 更高的并发性能
- 更简单的并发编程模型
