Java 类类型

Note: This article has been written with the assistance of AI.

普通类 (Regular Class)

类的定义和基本结构

类的定义语法

[访问修饰符] class 类名 [extends 父类] [implements 接口1, 接口2, ...] {
    // 成员变量
    // 构造方法
    // 成员方法
    // 代码块
    // 内部类
}

基本示例

public class Person {
    // 成员变量
    private String name;
    private int age;
    
    // 构造方法
    public Person() {
        // 默认构造方法
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 成员方法
    public void introduce() {
        System.out.println("我叫" + name + ",今年" + age + "岁");
    }
    
    // getter和setter方法
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        }
    }
}

访问修饰符

类级别的访问修饰符

// public类:在任何地方都可以访问
public class PublicClass {
    // ...
}

// 默认修饰符类:只能在同一个包内访问
class DefaultClass {
    // ...
}

// 注意:一个Java文件中只能有一个public类

成员级别的访问修饰符

public class AccessExample {
    public String publicVar = "公共变量";      // 任何地方都可以访问
    protected String protectedVar = "受保护变量"; // 同包或子类可以访问
    String defaultVar = "默认变量";           // 同包可以访问
    private String privateVar = "私有变量";    // 只能在本类中访问
    
    // 方法同样适用这些修饰符
    public void publicMethod() {}
    protected void protectedMethod() {}
    void defaultMethod() {}
    private void privateMethod() {}
}

成员变量

变量类型

public class VariableTypes {
    // 实例变量 - 每个对象都有自己的副本
    private String instanceVar;
    
    // 类变量(静态变量) - 所有对象共享
    private static int classVar;
    
    // 常量
    public static final double PI = 3.14159;
    
    // 易变变量(多线程环境下使用)
    private volatile boolean flag;
    
    // 瞬态变量(不被序列化)
    private transient String tempData;
}

实例变量 (Instance Variables)

  • 属于对象的实例,每个对象都有自己独立的副本
  • 生命周期与对象相同,随对象创建而创建,随对象销毁而销毁
  • 用于存储对象的状态信息
public class Student {
    // 实例变量
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;  // 使用this区分实例变量和参数
        this.age = age;
    }
    
    public void displayInfo() {
        System.out.println("Name: " + name + ", Age: " + age);
    }
    
    public static void main(String[] args) {
        Student student1 = new Student("Alice", 20);
        Student student2 = new Student("Bob", 22);
        
        student1.displayInfo();  // 输出: Name: Alice, Age: 20
        student2.displayInfo();  // 输出: Name: Bob, Age: 22
        
        // 每个对象有独立的实例变量副本
        System.out.println(student1.name);  // Alice
        System.out.println(student2.name);  // Bob (不同的值)
    }
}

类变量/静态变量 (Class/Static Variables)

  • 属于类本身,所有对象共享同一个副本
  • 在类加载时初始化,程序结束时销毁
  • 用于存储类级别的共享数据
public class Employee {
    // 实例变量
    private String name;
    
    // 类变量 - 所有员工共享
    private static int employeeCount = 0;
    private static String companyName = "Tech Corp";
    
    public Employee(String name) {
        this.name = name;
        employeeCount++;  // 每次创建对象时递增共享计数器
    }
    
    public static void displayCompanyInfo() {
        System.out.println("Company: " + companyName);
        System.out.println("Total Employees: " + employeeCount);
        // System.out.println(name);  // 错误!静态方法不能访问实例变量
    }
    
    public static void setCompanyName(String newName) {
        companyName = newName;  // 修改影响所有对象
    }
    
    public static void main(String[] args) {
        Employee emp1 = new Employee("John");
        Employee emp2 = new Employee("Jane");
        
        Employee.displayCompanyInfo();
        // 输出:
        // Company: Tech Corp
        // Total Employees: 2
        
        Employee.setCompanyName("New Tech Corp");
        Employee.displayCompanyInfo();
        // 输出:
        // Company: New Tech Corp  
        // Total Employees: 2
    }
}

常量 (Constants)

  • 使用 final 关键字声明,值一旦设定就不能修改
  • 通常与 static 结合使用,作为类级别的常量
  • 命名约定:全大写,单词间用下划线分隔
public class MathConstants {
    // 常量
    public static final double PI = 3.141592653589793;
    public static final double E = 2.718281828459045;
    public static final int MAX_RETRY_COUNT = 3;
    
    // 实例常量 - 每个对象有自己的副本,但创建后不能修改
    private final long creationTime;
    
    public MathConstants() {
        this.creationTime = System.currentTimeMillis();  // 只能在构造函数中赋值
    }
    
    public double calculateCircleArea(double radius) {
        return PI * radius * radius;  // 使用常量
    }
    
    public static void main(String[] args) {
        System.out.println("PI: " + MathConstants.PI);
        System.out.println("E: " + MathConstants.E);
        
        MathConstants math = new MathConstants();
        double area = math.calculateCircleArea(5.0);
        System.out.println("Area: " + area);
        
        // MathConstants.PI = 3.14;  // 编译错误!常量不能修改
    }
}

易变变量 (Volatile Variables)

  • 确保多线程环境下变量的可见性
  • 防止指令重排序优化
  • 不保证原子性,适合作为状态标志
public class VolatileExample {
    // 易变变量 - 确保多线程可见性
    private volatile boolean running = true;
    private volatile int counter = 0;
    
    public void startWorker() {
        Thread worker = new Thread(() -> {
            while (running) {  // 其他线程修改running时立即可见
                counter++;
                try {
                    System.out.println(running + " Counter: " + counter);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println(running + " Worker stopped. Counter: " + counter);
        });
        worker.start();
    }
    
    public void stopWorker() {
        running = false;  // 主线程修改,工作线程立即可见
    }
    
    public static void main(String[] args) throws InterruptedException {
        VolatileExample example = new VolatileExample();
        example.startWorker();
        
        Thread.sleep(1000);  // 让工作线程运行1秒
        example.stopWorker();
        
        Thread.sleep(100);  // 给工作线程时间结束
    }
}
可见性保证
  • 问题:在多核CPU架构下,每个线程可能有自己的缓存,对变量的修改可能不会立即对其他线程可见
  • 解决volatile确保当一个线程修改变量时,新值立即被写回主内存,其他线程读取时直接从主内存获取最新值
防止指令重排序
  • 问题:JVM和处理器会对指令进行重排序优化,可能破坏程序的预期执行顺序
  • 解决volatile建立"happens-before"关系,确保在volatile写操作之前的所有操作都对后续的读操作可见
不保证原子性
  • 限制volatile不保证复合操作的原子性(如i++)
  • 适用场景:适合作为简单的状态标志,不适合需要原子性的计数器等场景
详细示例代码
示例1:可见性问题的演示和解决
public class VisibilityExample {
    // 不使用 volatile - 可能出现可见性问题
    private static boolean stopRequested = false;
    
    // 使用 volatile - 确保可见性
    private static volatile boolean volatileStopRequested = false;
    
    public static void main(String[] args) throws InterruptedException {
        demonstrateVisibilityProblem();
        Thread.sleep(1000);
        demonstrateVolatileSolution();
    }
    
    // 演示可见性问题
    public static void demonstrateVisibilityProblem() throws InterruptedException {
        stopRequested = false;
        
        Thread worker = new Thread(() -> {
            int count = 0;
            while (!stopRequested) {
                count++;
                // 一些处理工作
            }
            System.out.println("普通变量 - 工作线程结束,循环次数: " + count);
        });
        
        worker.start();
        Thread.sleep(100); // 确保工作线程开始运行
        
        stopRequested = true; // 主线程修改标志
        System.out.println("普通变量 - 主线程设置了停止标志");
        
        worker.join(1000); // 等待工作线程结束,最多1秒
        if (worker.isAlive()) {
            System.out.println("普通变量 - 工作线程未停止!存在可见性问题");
            worker.interrupt();
        }
    }
    
    // 演示volatile解决方案
    public static void demonstrateVolatileSolution() throws InterruptedException {
        volatileStopRequested = false;
        
        Thread worker = new Thread(() -> {
            int count = 0;
            while (!volatileStopRequested) {
                count++;
                // 一些处理工作
            }
            System.out.println("Volatile变量 - 工作线程结束,循环次数: " + count);
        });
        
        worker.start();
        Thread.sleep(100); // 确保工作线程开始运行
        
        volatileStopRequested = true; // 主线程修改标志
        System.out.println("Volatile变量 - 主线程设置了停止标志");
        
        worker.join(1000);
        if (!worker.isAlive()) {
            System.out.println("Volatile变量 - 工作线程成功停止");
        }
    }
}
示例2:指令重排序的防止

正常情况下(无重排序):

  • 线程1执行:a = 1x = b
  • 线程2执行:b = 1y = a

可能的执行结果:

  • x=0, y=1(线程1先执行完)
  • x=1, y=0(线程2先执行完)
  • x=1, y=1(两个线程交错执行)

理论上不可能出现 x=0, y=0

由于编译器和处理器的优化,实际执行顺序可能变成:

// 线程1可能重排序为:
x = b;  // 先读b
a = 1;  // 后写a

// 线程2可能重排序为:
y = a;  // 先读a  
b = 1;  // 后写b

这样就会出现:

  1. 线程1先执行 x = b(此时b=0,所以x=0)
  2. 线程2先执行 y = a(此时a=0,所以y=0)
  3. 然后两个线程分别执行赋值操作

结果x=0, y=0,违反了程序逻辑预期!

package VolatileVariables;

public class InstructionReorderingExample {
    private static int x = 0, y = 0;
    private static int a = 0, b = 0;
    
    // 使用volatile防止重排序
    private static volatile boolean ready = false;
    private static volatile int result = 0;
    
    public static void main(String[] args) throws InterruptedException {
        // 演示指令重排序问题
        demonstrateReordering();
        
        Thread.sleep(1000);
        
        // 演示volatile解决方案
        demonstrateVolatilePrevention();
    }
    
    // 演示指令重排序问题
    public static void demonstrateReordering() throws InterruptedException {
        int count = 0;
        
        for (int i = 0; i < 100000; i++) {
            x = y = a = b = 0;
            
            Thread one = new Thread(() -> {
                a = 1;
                x = b;
            });
            
            Thread two = new Thread(() -> {
                b = 1;
                y = a;
            });
            
            one.start();
            two.start();
            one.join();
            two.join();
            
            // 如果指令没有重排序,x和y不可能同时为0
            if (x == 0 && y == 0) {
                count++;
                System.out.println("检测到指令重排序! 次数: " + count);
            } else {
                System.out.println("指令没有重排序!");
            }   
        }
    }
    
    // 演示volatile防止重排序
    public static void demonstrateVolatilePrevention() {
        Thread writer = new Thread(() -> {
            // 这些操作在ready赋值之前完成,且对reader线程可见
            result = 42;
            ready = true; // volatile写,建立happens-before关系
        });
        
        Thread reader = new Thread(() -> {
            if (ready) { // volatile读,看到writer线程的所有写操作
                System.out.println("结果: " + result); // 保证看到42,而不是0
            }
        });
        
        writer.start();
        reader.start();
    }
}
示例3:原子性限制的演示
public class AtomicityExample {
    // volatile不保证原子性
    private static volatile int volatileCounter = 0;
    
    // 使用AtomicInteger保证原子性
    private static java.util.concurrent.atomic.AtomicInteger atomicCounter = 
        new java.util.concurrent.atomic.AtomicInteger(0);
    
    // 使用synchronized保证原子性
    private static int synchronizedCounter = 0;
    
    public static void main(String[] args) throws InterruptedException {
        demonstrateVolatileAtomicityProblem();
        Thread.sleep(1000);
        demonstrateAtomicSolution();
        Thread.sleep(1000);
        demonstrateSynchronizedSolution();
    }
    
    // 演示volatile的原子性问题
    public static void demonstrateVolatileAtomicityProblem() throws InterruptedException {
        volatileCounter = 0;
        
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    volatileCounter++; // 这不是原子操作!
                }
            });
        }
        
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        
        System.out.println("Volatile计数器期望值: 10000, 实际值: " + volatileCounter);
    }
    
    // 演示AtomicInteger解决方案
    public static void demonstrateAtomicSolution() throws InterruptedException {
        atomicCounter.set(0);
        
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    atomicCounter.incrementAndGet(); // 原子操作
                }
            });
        }
        
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        
        System.out.println("Atomic计数器期望值: 10000, 实际值: " + atomicCounter.get());
    }
    
    // 演示synchronized解决方案
    public static void demonstrateSynchronizedSolution() throws InterruptedException {
        synchronizedCounter = 0;
        
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    incrementSynchronized(); // 同步方法
                }
            });
        }
        
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        
        System.out.println("Synchronized计数器期望值: 10000, 实际值: " + synchronizedCounter);
    }
    
    private static synchronized void incrementSynchronized() {
        synchronizedCounter++;
    }
}
示例4:正确的volatile使用场景 - 状态标志
public class CorrectVolatileUsage {
    // 正确的volatile使用 - 状态标志
    private volatile boolean shutdownRequested = false;
    
    // 配置信息 - 适合使用volatile(发布-读取模式)
    private volatile Configuration config = new Configuration("default", 1000);
    
    private static class Configuration {
        private final String name;
        private final int timeout;
        
        public Configuration(String name, int timeout) {
            this.name = name;
            this.timeout = timeout;
        }
        
        @Override
        public String toString() {
            return "Configuration{name='" + name + "', timeout=" + timeout + "}";
        }
    }
    
    public void startServer() {
        Thread serverThread = new Thread(() -> {
            while (!shutdownRequested) {
                try {
                    // 模拟服务器工作
                    processRequest();
                    
                    // 读取当前配置(volatile保证看到最新值)
                    Configuration currentConfig = config;
                    System.out.println("使用配置: " + currentConfig);
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println("服务器正常关闭");
        });
        
        serverThread.start();
    }
    
    public void requestShutdown() {
        shutdownRequested = true; // volatile写,服务器线程立即可见
        System.out.println("关闭请求已发送");
    }
    
    public void updateConfiguration(Configuration newConfig) {
        config = newConfig; // volatile写,新配置立即可见
        System.out.println("配置已更新: " + newConfig);
    }
    
    private void processRequest() throws InterruptedException {
        Thread.sleep(500); // 模拟请求处理
    }
    
    public static void main(String[] args) throws InterruptedException {
        CorrectVolatileUsage server = new CorrectVolatileUsage();
        
        server.startServer();
        
        // 运行一段时间后更新配置
        Thread.sleep(2000);
        server.updateConfiguration(new Configuration("production", 2000));
        
        // 再运行一段时间后关闭
        Thread.sleep(2000);
        server.requestShutdown();
    }
}
示例5:双重检查锁定模式
public class DoubleCheckedLocking {
    // 使用volatile的单例模式
    private static volatile DoubleCheckedLocking instance;
    
    private final String data;
    
    private DoubleCheckedLocking() {
        // 模拟耗时的初始化
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        this.data = "初始化数据";
    }
    
    // 正确的双重检查锁定
    public static DoubleCheckedLocking getInstance() {
        if (instance == null) { // 第一次检查(不加锁)
            synchronized (DoubleCheckedLocking.class) {
                if (instance == null) { // 第二次检查(加锁)
                    instance = new DoubleCheckedLocking(); // volatile写
                }
            }
        }
        return instance;
    }
    
    // 错误的实现(不使用volatile)
    private static DoubleCheckedLocking brokenInstance;
    
    public static DoubleCheckedLocking getBrokenInstance() {
        if (brokenInstance == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (brokenInstance == null) {
                    brokenInstance = new DoubleCheckedLocking(); // 可能发生重排序
                }
            }
        }
        return brokenInstance;
    }
    
    public String getData() {
        return data;
    }
    
    public static void main(String[] args) {
        // 测试正确的实现
        Thread t1 = new Thread(() -> {
            DoubleCheckedLocking instance = DoubleCheckedLocking.getInstance();
            System.out.println("线程1获取实例: " + instance.getData());
        });
        
        Thread t2 = new Thread(() -> {
            DoubleCheckedLocking instance = DoubleCheckedLocking.getInstance();
            System.out.println("线程2获取实例: " + instance.getData());
        });
        
        t1.start();
        t2.start();
    }
}
总结:使用volatile的场景
  1. 状态标志 - 简单的boolean标志,用于控制线程执行
  2. 一次性安全发布 - 确保对象构造完成后才对其他线程可见
  3. 独立观察 - 定期"发布"观察结果供程序使用
  4. 双重检查锁定 - 与synchronized配合实现延迟初始化
总结:不使用volatile的场景
  1. 复合操作 - i++、check-then-act等需要原子性的操作
  2. 多个相关变量 - 需要同时更新多个相关变量时
  3. 频繁写入 - 写入频繁且需要原子性时,考虑使用锁
总结:volatile vs synchronized
特性 volatile synchronized
可见性 ✅ 保证 ✅ 保证
原子性 ❌ 不保证 ✅ 保证
互斥性 ❌ 不提供 ✅ 提供
性能 较高 较低
适用场景 状态标志、一次性发布 复合操作、临界区

瞬态变量 (Transient Variables)

  • 标记变量不被序列化
  • 用于存储临时数据或敏感信息
  • 反序列化时被设为默认值
import java.io.*;

class User implements Serializable {
    // 会被序列化
    private String username;
    private String email;
    
    // 不会被序列化
    private transient String password;
    private transient Thread currentThread;  // Thread不可序列化
    
    // 缓存数据,不需要序列化
    private transient String cachedDisplayName;
    
    public User(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
        this.currentThread = Thread.currentThread();
        updateCachedDisplayName();
    }
    
    private void updateCachedDisplayName() {
        this.cachedDisplayName = username + " <" + email + ">";
    }
    
    public void displayInfo() {
        System.out.println("Username: " + username);
        System.out.println("Email: " + email);
        System.out.println("Password: " + (password != null ? "***" : "null"));
        System.out.println("Thread: " + (currentThread != null ? currentThread.getName() : "null"));
        System.out.println("Cached: " + cachedDisplayName);
    }
    
    // 反序列化后的回调方法
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        // 重新计算瞬态变量
        updateCachedDisplayName();
        currentThread = Thread.currentThread();
    }
}

public class TransientExample {
    public static void main(String[] args) {
        User user = new User("john_doe", "john@example.com", "secret123");
        
        System.out.println("=== 原始对象 ===");
        user.displayInfo();
        
        // 序列化
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("user.ser"))) {
            oos.writeObject(user);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream("user.ser"))) {
            User deserializedUser = (User) ois.readObject();
            
            System.out.println("\n=== 反序列化后的对象 ===");
            deserializedUser.displayInfo();  // password为null,cachedDisplayName被重新计算
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
阻止序列化
  • 作用:标记的变量在对象序列化时会被跳过,不写入字节流
  • 效果:减少序列化数据大小,保护敏感信息
默认值恢复
  • 反序列化:被标记为transient的变量在反序列化时会被设为默认值
  • 默认值:对象为null,数值类型为0,boolean为false
适用场景
  • 临时计算数据、缓存结果
  • 敏感信息(密码、密钥等)
  • 不可序列化的对象引用
  • 运行时状态信息
详细示例代码
示例1:基础使用和序列化效果演示
import java.io.*;
import java.util.Date;

class User implements Serializable {
    // 会被序列化的字段
    private String username;
    private String email;
    private Date registrationDate;
    
    // 不会被序列化的字段
    private transient String password;
    private transient int loginCount;  // 临时统计信息
    private transient String sessionId; // 会话ID
    
    public User(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
        this.registrationDate = new Date();
        this.loginCount = 0;
        generateSessionId();
    }
    
    public void login() {
        loginCount++;
        generateSessionId();
        System.out.println(username + " 登录成功,登录次数: " + loginCount);
    }
    
    private void generateSessionId() {
        this.sessionId = "SESSION_" + System.currentTimeMillis() + "_" + username;
    }
    
    public void displayUserInfo() {
        System.out.println("=== 用户信息 ===");
        System.out.println("用户名: " + username);
        System.out.println("邮箱: " + email);
        System.out.println("密码: " + (password != null ? "***" : "null"));
        System.out.println("注册时间: " + registrationDate);
        System.out.println("登录次数: " + loginCount);
        System.out.println("会话ID: " + sessionId);
        System.out.println();
    }
}

public class BasicTransientExample {
    public static void main(String[] args) {
        // 创建用户对象
        User user = new User("alice", "alice@example.com", "secret123");
        user.login();
        user.login(); // 模拟两次登录
        
        System.out.println("=== 原始对象 ===");
        user.displayUserInfo();
        
        // 序列化到文件
        String filename = "user.dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(filename))) {
            oos.writeObject(user);
            System.out.println("对象序列化完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 从文件反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(filename))) {
            User deserializedUser = (User) ois.readObject();
            
            System.out.println("=== 反序列化后的对象 ===");
            deserializedUser.displayUserInfo();
            // 注意:password为null,loginCount为0,sessionId为null
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
示例2:敏感信息保护
import java.io.*;
import java.util.Arrays;

class BankAccount implements Serializable {
    private String accountNumber;
    private String accountHolder;
    private double balance;
    
    // 敏感信息 - 不序列化
    private transient char[] password;
    private transient String securityQuestion;
    private transient String securityAnswer;
    
    // 临时数据 - 不序列化
    private transient String lastTransactionId;
    private transient boolean isLoggedIn;
    
    public BankAccount(String accountNumber, String accountHolder, 
                      double balance, char[] password, 
                      String securityQuestion, String securityAnswer) {
        this.accountNumber = accountNumber;
        this.accountHolder = accountHolder;
        this.balance = balance;
        this.password = password;
        this.securityQuestion = securityQuestion;
        this.securityAnswer = securityAnswer;
        this.isLoggedIn = false;
    }
    
    public boolean login(char[] inputPassword) {
        if (Arrays.equals(password, inputPassword)) {
            isLoggedIn = true;
            generateTransactionId();
            return true;
        }
        return false;
    }
    
    public void deposit(double amount) {
        if (isLoggedIn && amount > 0) {
            balance += amount;
            generateTransactionId();
            System.out.println("存款成功: " + amount);
        }
    }
    
    private void generateTransactionId() {
        this.lastTransactionId = "TXN_" + System.currentTimeMillis();
    }
    
    // 自定义序列化逻辑
    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject(); // 序列化非transient字段
        // 不写入password等敏感信息
        System.out.println("序列化完成 - 敏感信息已被排除");
    }
    
    // 自定义反序列化逻辑
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject(); // 反序列化非transient字段
        // transient字段保持为默认值
        this.password = null;
        this.securityQuestion = null;
        this.securityAnswer = null;
        this.isLoggedIn = false;
        System.out.println("反序列化完成 - 需要重新登录");
    }
    
    // 清理敏感信息
    public void clearSensitiveData() {
        if (password != null) {
            Arrays.fill(password, '0'); // 覆盖密码数据
            password = null;
        }
        securityQuestion = null;
        securityAnswer = null;
    }
    
    public void displayAccountInfo() {
        System.out.println("=== 账户信息 ===");
        System.out.println("账户号: " + accountNumber);
        System.out.println("持有人: " + accountHolder);
        System.out.println("余额: " + balance);
        System.out.println("密码: " + (password != null ? "***" : "null"));
        System.out.println("安全提示: " + securityQuestion);
        System.out.println("登录状态: " + isLoggedIn);
        System.out.println("最后交易ID: " + lastTransactionId);
        System.out.println();
    }
    
    @Override
    protected void finalize() throws Throwable {
        clearSensitiveData(); // 确保敏感数据被清理
        super.finalize();
    }
}

public class SensitiveDataExample {
    public static void main(String[] args) {
        // 创建银行账户
        char[] password = "securePass123".toCharArray();
        BankAccount account = new BankAccount(
            "123456789", 
            "张三", 
            5000.0, 
            password,
            "你出生的城市?",
            "北京"
        );
        
        // 登录并执行操作
        account.login(password);
        account.deposit(1000);
        
        System.out.println("=== 原始账户对象 ===");
        account.displayAccountInfo();
        
        // 序列化
        String filename = "account.dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(filename))) {
            oos.writeObject(account);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(filename))) {
            BankAccount restoredAccount = (BankAccount) ois.readObject();
            
            System.out.println("=== 恢复的账户对象 ===");
            restoredAccount.displayAccountInfo();
            
            // 需要重新登录
            char[] newPassword = "securePass123".toCharArray();
            boolean loginSuccess = restoredAccount.login(newPassword);
            System.out.println("重新登录结果: " + loginSuccess);
            
            Arrays.fill(newPassword, '0'); // 清理密码数组
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        // 清理原始对象的敏感数据
        account.clearSensitiveData();
    }
}
示例3:不可序列化对象处理
import java.io.*;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.concurrent.ThreadPoolExecutor;

class NetworkService implements Serializable {
    private String serviceName;
    private String host;
    private int port;
    
    // 不可序列化的对象必须标记为transient
    private transient Socket connection;
    private transient ThreadPoolExecutor executor;
    private transient Runtime runtime;
    
    // 临时状态信息
    private transient LocalDateTime lastConnected;
    private transient boolean isConnected;
    
    // 用于重建的配置信息
    private long connectionTimeout;
    private int maxThreads;
    
    public NetworkService(String serviceName, String host, int port) {
        this.serviceName = serviceName;
        this.host = host;
        this.port = port;
        this.connectionTimeout = 5000L;
        this.maxThreads = 10;
        initializeTransientFields();
    }
    
    private void initializeTransientFields() {
        this.runtime = Runtime.getRuntime();
        this.lastConnected = LocalDateTime.now();
        this.isConnected = false;
        System.out.println("初始化瞬态字段完成");
    }
    
    public void connect() {
        try {
            // 模拟网络连接
            System.out.println("连接到 " + host + ":" + port);
            this.isConnected = true;
            this.lastConnected = LocalDateTime.now();
        } catch (Exception e) {
            System.out.println("连接失败: " + e.getMessage());
        }
    }
    
    // 自定义序列化方法
    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject(); // 序列化非transient字段
        // 不保存连接状态
        System.out.println("序列化: 保存服务配置,跳过网络连接状态");
    }
    
    // 自定义反序列化方法
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject(); // 反序列化非transient字段
        // 重新初始化transient字段
        initializeTransientFields();
        System.out.println("反序列化: 重新初始化瞬态字段");
    }
    
    public void displayServiceInfo() {
        System.out.println("=== 服务信息 ===");
        System.out.println("服务名称: " + serviceName);
        System.out.println("主机: " + host);
        System.out.println("端口: " + port);
        System.out.println("连接状态: " + isConnected);
        System.out.println("最后连接: " + lastConnected);
        System.out.println("Socket: " + (connection != null ? "已初始化" : "null"));
        System.out.println("Executor: " + (executor != null ? "已初始化" : "null"));
        System.out.println("Runtime: " + (runtime != null ? "可用" : "null"));
        System.out.println();
    }
    
    // 重新连接方法
    public void reconnect() {
        System.out.println("重新建立连接...");
        connect();
    }
}

public class NonSerializableExample {
    public static void main(String[] args) {
        // 创建网络服务
        NetworkService service = new NetworkService("DataService", "api.example.com", 8080);
        service.connect();
        
        System.out.println("=== 原始服务对象 ===");
        service.displayServiceInfo();
        
        // 序列化
        String filename = "service.dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(filename))) {
            oos.writeObject(service);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(filename))) {
            NetworkService restoredService = (NetworkService) ois.readObject();
            
            System.out.println("=== 恢复的服务对象 ===");
            restoredService.displayServiceInfo();
            
            // 需要重新连接
            restoredService.reconnect();
            restoredService.displayServiceInfo();
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
示例4:缓存数据和计算结果的transient使用
import java.io.*;
import java.util.ArrayList;
import java.util.List;

class DataProcessor implements Serializable {
    private String dataSource;
    private List<Integer> rawData;
    
    // 缓存的计算结果 - 不需要序列化
    private transient Integer cachedSum;
    private transient Double cachedAverage;
    private transient List<Integer> cachedSortedData;
    
    // 计算状态
    private transient boolean isCalculated;
    private transient long calculationTime;
    
    public DataProcessor(String dataSource) {
        this.dataSource = dataSource;
        this.rawData = new ArrayList<>();
        this.isCalculated = false;
    }
    
    public void addData(int value) {
        rawData.add(value);
        invalidateCache(); // 数据变化时使缓存失效
    }
    
    private void invalidateCache() {
        cachedSum = null;
        cachedAverage = null;
        cachedSortedData = null;
        isCalculated = false;
    }
    
    public void calculate() {
        if (!isCalculated) {
            long startTime = System.currentTimeMillis();
            
            // 计算总和
            cachedSum = rawData.stream().mapToInt(Integer::intValue).sum();
            
            // 计算平均值
            cachedAverage = rawData.isEmpty() ? 0.0 : 
                rawData.stream().mapToInt(Integer::intValue).average().orElse(0.0);
            
            // 排序数据
            cachedSortedData = new ArrayList<>(rawData);
            cachedSortedData.sort(Integer::compareTo);
            
            calculationTime = System.currentTimeMillis() - startTime;
            isCalculated = true;
            
            System.out.println("计算完成,耗时: " + calculationTime + "ms");
        }
    }
    
    public void displayResults() {
        System.out.println("=== 数据处理结果 ===");
        System.out.println("数据源: " + dataSource);
        System.out.println("原始数据: " + rawData);
        System.out.println("数据总和: " + (cachedSum != null ? cachedSum : "未计算"));
        System.out.println("平均值: " + (cachedAverage != null ? cachedAverage : "未计算"));
        System.out.println("排序数据: " + (cachedSortedData != null ? cachedSortedData : "未计算"));
        System.out.println("计算状态: " + isCalculated);
        System.out.println();
    }
    
    // 自定义序列化
    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject(); // 只保存原始数据
        System.out.println("序列化: 保存原始数据,跳过缓存结果");
    }
    
    // 自定义反序列化
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        // 重新初始化transient字段
        this.isCalculated = false;
        this.cachedSum = null;
        this.cachedAverage = null;
        this.cachedSortedData = null;
        System.out.println("反序列化: 重新初始化缓存字段");
    }
    
    // 重新计算方法
    public void recalculate() {
        System.out.println("重新计算数据...");
        calculate();
    }
}

public class CacheDataExample {
    public static void main(String[] args) {
        // 创建数据处理器
        DataProcessor processor = new DataProcessor("sensor_data");
        
        // 添加数据
        processor.addData(10);
        processor.addData(25);
        processor.addData(5);
        processor.addData(30);
        processor.addData(15);
        
        // 计算并显示结果
        processor.calculate();
        System.out.println("=== 原始对象(计算后) ===");
        processor.displayResults();
        
        // 序列化
        String filename = "processor.dat";
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(filename))) {
            oos.writeObject(processor);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(filename))) {
            DataProcessor restoredProcessor = (DataProcessor) ois.readObject();
            
            System.out.println("=== 恢复的对象 ===");
            restoredProcessor.displayResults(); // 缓存数据丢失
            
            // 重新计算
            restoredProcessor.recalculate();
            restoredProcessor.displayResults();
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
总结:transient 关键字的主要用途
  1. 安全保护

    • 防止敏感信息(密码、密钥等)被持久化
    • 避免安全漏洞
  2. 资源优化

    • 减少序列化数据大小
    • 避免序列化大型临时数据
  3. 运行时状态管理

    • 不保存临时状态信息
    • 重新创建对象时初始化新状态
  4. 不可序列化对象处理

    • 处理Socket、Thread等不可序列化的对象引用
    • 在反序列化时重新创建这些资源

最佳实践:

  • writeObject/readObject方法中自定义序列化逻辑
  • 及时清理敏感数据的内存
  • 为transient字段提供重新初始化的方法
  • 考虑使用@Transient注解(JPA)与transient关键字的区别

变量的访问规则

静态方法不能直接访问实例变量,但实例方法可以访问静态变量。

静态方法不能直接访问实例变量
public class VariableExample {
    // 实例变量
    private String instanceVar = "实例变量";
    
    // 静态变量
    private static String staticVar = "静态变量";
    
    // 静态方法
    public static void staticMethod() {
        // ❌ 编译错误:不能直接访问实例变量
        System.out.println(instanceVar);
        
        // ✅ 正确:可以访问静态变量
        System.out.println(staticVar);
        
        // ✅ 正确:通过对象实例访问实例变量
        VariableExample obj = new VariableExample();
        System.out.println(obj.instanceVar);
    }
}
实例方法可以访问所有变量
public class VariableExample {
    // 实例变量
    private String instanceVar = "实例变量";
    
    // 静态变量
    private static String staticVar = "静态变量";
    
    // 实例方法
    public void instanceMethod() {
        // ✅ 正确:访问自己的实例变量
        System.out.println(instanceVar);
        
        // ✅ 正确:访问静态变量
        System.out.println(staticVar);
        
        // ✅ 正确:访问其他对象的实例变量
        VariableExample other = new VariableExample();
        System.out.println(other.instanceVar);
    }
}
示例
public class VariableAccessDemo {
    // 实例变量
    private int instanceCount = 10;
    
    // 静态变量  
    private static int staticCount = 20;
    
    // 静态方法
    public static void staticMethod() {
        // System.out.println(instanceCount); // ❌ 编译错误
        
        System.out.println("静态方法访问静态变量: " + staticCount); // ✅
        
        // 通过创建对象访问实例变量
        VariableAccessDemo obj = new VariableAccessDemo();
        System.out.println("通过对象访问实例变量: " + obj.instanceCount); // ✅
    }
    
    // 实例方法
    public void instanceMethod() {
        System.out.println("实例方法访问实例变量: " + instanceCount); // ✅
        System.out.println("实例方法访问静态变量: " + staticCount); // ✅
        
        // 修改静态变量
        staticCount++;
        System.out.println("修改后静态变量: " + staticCount);
    }
    
    public static void main(String[] args) {
        // 静态方法调用
        staticMethod();
        
        // 实例方法调用
        VariableAccessDemo demo = new VariableAccessDemo();
        demo.instanceMethod();
    }
}
访问规则总结
方法/变量类型 实例变量 静态变量
静态方法 ❌ 不能直接访问
✅ 可通过对象访问
✅ 可以直接访问
实例方法 ✅ 可以直接访问 ✅ 可以直接访问
根本原因

生命周期不同

  • 静态变量:类加载时初始化,程序结束时销毁
  • 实例变量:对象创建时初始化,对象销毁时回收
  • 静态方法:不需要对象实例即可调用
  • 实例方法:必须通过对象实例调用

因此

  • 静态方法调用时,可能还没有实例变量存在
  • 实例方法调用时,静态变量肯定已经存在

变量初始化

public class VariableInitialization {
    // 直接初始化
    private String name = "默认名称";
    private int age = 0;
    
    // 静态变量初始化
    private static int count = 0;
    
    // 使用代码块初始化
    private List<String> list;
    
    {
        // 实例初始化块
        list = new ArrayList<>();
        list.add("item1");
        list.add("item2");
    }
    
    static {
        // 静态初始化块
        count = 100;
    }
}

构造方法

构造方法类型

public class ConstructorExample {
    private String name;
    private int age;
    private String address;
    
    // 默认构造方法
    public ConstructorExample() {
        this.name = "未知";
        this.age = 0;
        this.address = "未知地址";
    }
    
    // 带参数构造方法
    public ConstructorExample(String name, int age) {
        this.name = name;
        this.age = age;
        this.address = "未知地址";
    }
    
    // 构造方法重载
    public ConstructorExample(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    
    // 拷贝构造方法
    public ConstructorExample(ConstructorExample other) {
        this.name = other.name;
        this.age = other.age;
        this.address = other.address;
    }
    
    // 构造方法调用其他构造方法(必须第一行)
    public ConstructorExample(String name) {
        this(name, 0, "未知地址");
    }
}

成员方法

方法定义

public class MethodExample {
    // 无返回值方法
    public void printInfo() {
        System.out.println("这是一个无返回值方法");
    }
    
    // 有返回值方法
    public int calculateSum(int a, int b) {
        return a + b;
    }
    
    // 静态方法
    public static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
    
    // final方法(不能被子类重写)
    public final void finalMethod() {
        System.out.println("这是一个final方法");
    }
    
    // 可变参数方法
    public void varArgsMethod(String... strings) {
        for (String str : strings) {
            System.out.println(str);
        }
    }
}

实例方法可以访问静态方法,但静态方法不能直接访问实例方法。

静态方法不能直接访问实例方法

public class Example {
    private String instanceVariable = "实例变量";
    
    // 实例方法
    public void instanceMethod() {
        System.out.println("实例方法");
    }
    
    // 静态方法
    public static void staticMethod() {
        // 编译错误!不能直接访问实例方法
        instanceMethod(); // ❌ 错误
        
        // 编译错误!不能直接访问实例变量
        System.out.println(instanceVariable); // ❌ 错误
    }
}

原因:静态方法属于类级别,在类加载时就可以调用,此时可能还没有创建任何对象实例。

实例方法可以访问静态方法

public class Example {
    private static String staticVariable = "静态变量";
    
    // 静态方法
    public static void staticMethod() {
        System.out.println("静态方法");
    }
    
    // 实例方法
    public void instanceMethod() {
        // ✅ 可以访问静态方法
        staticMethod();
        
        // ✅ 可以访问静态变量
        System.out.println(staticVariable);
        
        // ✅ 也可以访问自己的实例成员
        System.out.println("实例方法访问静态成员");
    }
}

原因:实例方法调用时,对象已经存在,静态成员也肯定已经初始化。

特殊情况:通过对象引用访问

public class Example {
    public void instanceMethod() {
        System.out.println("实例方法");
    }
    
    public static void staticMethod() {
        // 可以通过创建实例来访问实例方法
        Example obj = new Example();
        obj.instanceMethod(); // ✅ 正确
    }
}

总结表格

方法类型 能否访问实例方法 能否访问静态方法 能否访问实例变量 能否访问静态变量
静态方法 ❌ 不能直接访问 ✅ 可以访问 ❌ 不能直接访问 ✅ 可以访问
实例方法 ✅ 可以访问 ✅ 可以访问 ✅ 可以访问 ✅ 可以访问

记忆技巧

  • 静态的不能碰非静态的(直接访问)
  • 非静态的可以碰所有的
  • 静态成员属于类,实例成员属于对象

方法重载

public class MethodOverloading {
    // 方法重载:方法名相同,参数列表不同
    
    public void display() {
        System.out.println("无参数显示");
    }
    
    public void display(String message) {
        System.out.println("显示消息: " + message);
    }
    
    public void display(String message, int times) {
        for (int i = 0; i < times; i++) {
            System.out.println(message);
        }
    }
    
    public void display(int number) {
        System.out.println("显示数字: " + number);
    }
}

代码块

实例初始化块

public class InstanceBlockExample {
    private int x;
    private int y;
    
    // 实例初始化块 - 每次创建对象时执行
    {
        System.out.println("实例初始化块执行");
        x = 10;
        y = 20;
    }
    
    public InstanceBlockExample() {
        System.out.println("构造方法执行");
    }
}

静态初始化块

public class StaticBlockExample {
    private static int count;
    private static List<String> names;
    
    // 静态初始化块 - 类加载时执行一次
    static {
        System.out.println("静态初始化块执行");
        count = 0;
        names = new ArrayList<>();
        names.add("张三");
        names.add("李四");
    }
}

this & super 关键字

this关键字

this关键字代表当前对象的引用,指向调用该方法的对象实例。

区分成员变量和局部变量

public class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;  // this.name指成员变量,name指参数
        this.age = age;    // this.age指成员变量,age指参数
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

调用当前类的其他构造方法

public class Rectangle {
    private int width;
    private int height;
    private String color;
    
    // 无参构造
    public Rectangle() {
        this(10, 20);  // 调用有参构造
    }
    
    // 有参构造
    public Rectangle(int width, int height) {
        this(width, height, "red");  // 调用三参构造
    }
    
    // 三参构造
    public Rectangle(int width, int height, String color) {
        this.width = width;
        this.height = height;
        this.color = color;
    }
}

作为方法参数传递当前对象

public class Calculator {
    private int value;
    
    public Calculator(int value) {
        this.value = value;
    }
    
    public void display() {
        Printer.print(this);  // 将当前对象传递给其他方法
    }
}

class Printer {
    public static void print(Calculator calc) {
        System.out.println("Value: " + calc.value);
    }
}

返回当前对象(实现方法链)

public class StringBuilderExample {
    private StringBuilder sb = new StringBuilder();
    
    public StringBuilderExample append(String text) {
        sb.append(text);
        return this;  // 返回当前对象,支持链式调用
    }
    
    public StringBuilderExample appendLine(String text) {
        sb.append(text).append("\n");
        return this;
    }
    
    // 使用示例
    public static void main(String[] args) {
        StringBuilderExample example = new StringBuilderExample();
        example.append("Hello").appendLine(" World").append("Java");
        // 链式调用
    }
}

super关键字

super关键字代表父类对象的引用,用于访问父类的成员变量、方法和构造方法。

调用父类构造方法

class Animal {
    private String name;
    private int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 必须放在第一行,调用父类构造方法
        this.breed = breed;
    }
}

访问父类的成员变量

class Parent {
    protected String message = "Parent message";
}

class Child extends Parent {
    private String message = "Child message";
    
    public void display() {
        System.out.println("Child: " + this.message);      // 输出:Child message
        System.out.println("Parent: " + super.message);    // 输出:Parent message
    }
}

调用父类的方法

class Vehicle {
    public void start() {
        System.out.println("Vehicle starting...");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        super.start();  // 调用父类的start方法
        System.out.println("Car starting with ignition...");
    }
    
    public void test() {
        super.start();  // 仍然可以调用父类被重写的方法
    }
}

相同点

  • 都是引用类型
  • 都必须在非静态方法中使用
  • 都可以调用构造方法(必须放在第一行)

不同点

特性 this super
指向对象 当前对象 父类对象
调用构造方法 调用本类其他构造方法 调用父类构造方法
访问成员变量 访问本类成员变量 访问父类成员变量
访问方法 访问本类方法 访问父类方法
使用限制 可在任何非静态方法中使用 只能在子类中使用

使用场景

this的典型使用场景

public class Employee {
    private String id;
    private String name;
    private double salary;
    
    // 1. 区分同名变量
    public Employee(String id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }
    
    // 2. 构造方法重载调用
    public Employee() {
        this("E001", "Unknown", 0.0);
    }
    
    // 3. 返回当前对象实现链式调用
    public Employee setId(String id) {
        this.id = id;
        return this;
    }
    
    public Employee setName(String name) {
        this.name = name;
        return this;
    }
    
    // 使用示例
    public static void main(String[] args) {
        Employee emp = new Employee()
            .setId("E002")
            .setName("John")
            .setSalary(5000.0);
    }
}

super的典型使用场景

// 父类
class BankAccount {
    protected String accountNumber;
    protected double balance;
    
    public BankAccount(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }
    
    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount);
    }
    
    public void display() {
        System.out.println("Account: " + accountNumber + ", Balance: " + balance);
    }
}

// 子类
class SavingsAccount extends BankAccount {
    private double interestRate;
    
    public SavingsAccount(String accountNumber, double balance, double interestRate) {
        super(accountNumber, balance);  // 调用父类构造方法
        this.interestRate = interestRate;
    }
    
    @Override
    public void display() {
        super.display();  // 调用父类方法
        System.out.println("Interest Rate: " + interestRate + "%");
    }
    
    public void applyInterest() {
        double interest = balance * interestRate / 100;
        super.deposit(interest);  // 明确调用父类方法
    }
}

综合示例

class Person {
    protected String name;
    protected int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void introduce() {
        System.out.println("I'm " + name + ", " + age + " years old.");
    }
}

class Employee extends Person {
    private String employeeId;
    private double salary;
    
    public Employee(String name, int age, String employeeId, double salary) {
        super(name, age);  // 调用父类构造方法
        this.employeeId = employeeId;
        this.salary = salary;
    }
    
    @Override
    public void introduce() {
        super.introduce();  // 调用父类方法
        System.out.println("Employee ID: " + this.employeeId);  // 使用this访问当前类成员
        System.out.println("Salary: $" + this.salary);
    }
    
    // 使用this实现方法链
    public Employee setSalary(double salary) {
        this.salary = salary;
        return this;
    }
}

注意事项

  1. 构造方法调用顺序:使用this()super()调用构造方法时,必须放在方法的第一行
  2. 不能同时使用:在同一个构造方法中不能同时使用this()super()
  3. 静态上下文:在静态方法中不能使用thissuper
  4. 继承关系super只能在有继承关系的子类中使用

包和导入

包声明

package com.example.mypackage;

// 导入其他包中的类
import java.util.ArrayList;
import java.util.List;
import java.util.Date;

// 静态导入
import static java.lang.Math.PI;
import static java.lang.Math.pow;

public class PackageExample {
    private List<String> items;
    private Date createTime;
    
    public double calculateCircleArea(double radius) {
        return PI * pow(radius, 2);
    }
}
  • 普通导入:导入的是接口本身。在代码中可以使用短类名(如 ArrayList)而不是完全限定类名(如 java.util.ArrayList)。
  • 静态导入:导入的是类中的静态成员(静态变量或静态方法)。在代码中可以直接使用静态成员的名称,而无需通过类名来调用。
特性 普通导入 静态导入
导入目标 、接口、枚举 静态成员(静态变量、静态方法)
语法 import package.ClassName; import static package.ClassName.staticMember;
作用 简化类名的书写 省略调用静态成员时的类名
使用示例 使用 ArrayList 代替 java.util.ArrayList 使用 PIpow() 代替 Math.PIMath.pow()
可读性影响 通常提高可读性,代码更简洁 可能降低可读性,尤其是滥用时,会让人困惑某个方法或变量来自哪里

普通导入部分

import java.util.ArrayList; // 导入类
import java.util.List;      // 导入接口
import java.util.Date;      // 导入类

作用

  • 这行代码告诉编译器:“当我写下 List, ArrayList, Date 时,我指的是 java.util 包里的那些。”
  • 因此,可以在代码中直接使用:
private List<String> items;       // 而不是 java.util.List<String> items;
private Date createTime;          // 而不是 java.util.Date createTime;

如果没有普通导入,就必须使用完全限定名,代码会变得非常冗长:

private java.util.List<String> items;
private java.util.Date createTime;

静态导入部分

import static java.lang.Math.PI;  // 导入静态常量
import static java.lang.Math.pow; // 导入静态方法

作用

  • 这行代码告诉编译器:“当我写下 PIpow 时,我指的是 java.lang.Math 类中的静态常量 PI 和静态方法 pow。”
  • 因此,可以在 calculateCircleArea 方法中直接使用:
return PI * pow(radius, 2); // 而不是 Math.PI * Math.pow(radius, 2);

如果没有静态导入,就必须通过类名调用,这是更传统、更清晰的方式:

public double calculateCircleArea(double radius) {
    return Math.PI * Math.pow(radius, 2); // 明确指出了 PI 和 pow 的来源
}

封装性示例

封装是指将对象的属性(数据)和行为(方法)结合在一起,对外隐藏对象的内部细节,仅通过对象提供的接口与外界交互。

封装的目的是增强安全性和简化编程,使得对象更加独立。

public class BankAccount {
    // 私有成员变量,实现封装
    private String accountNumber;
    private String accountHolder;
    private double balance;
    private String password;
    
    public BankAccount(String accountNumber, String accountHolder, 
                      double initialBalance, String password) {
        this.accountNumber = accountNumber;
        this.accountHolder = accountHolder;
        this.balance = initialBalance;
        this.password = password;
    }
    
    // 公共方法提供对私有变量的受控访问
    public boolean deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            return true;
        }
        return false;
    }
    
    public boolean withdraw(double amount, String inputPassword) {
        if (authenticate(inputPassword) && amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }
    
    public double getBalance(String inputPassword) {
        if (authenticate(inputPassword)) {
            return balance;
        }
        return -1; // 表示认证失败
    }
    
    // 私有方法,内部使用
    private boolean authenticate(String inputPassword) {
        return this.password.equals(inputPassword);
    }
    
    // 只能获取,不能修改
    public String getAccountNumber() {
        return accountNumber;
    }
    
    public String getAccountHolder() {
        return accountHolder;
    }
}

复杂示例:学生管理系统设计

import java.util.ArrayList;
import java.util.List;

public class Student {
    // 静态变量 - 学生总数
    private static int totalStudents = 0;
    
    // 实例变量
    private final int studentId;  // final变量,一旦赋值不能修改
    private String name;
    private int age;
    private String className;
    private List<Double> scores;
    
    // 静态初始化块
    static {
        System.out.println("Student类被加载");
    }
    
    // 实例初始化块
    {
        scores = new ArrayList<>();
        totalStudents++;  // 每创建一个学生对象,总数加1
    }
    
    // 构造方法
    public Student(int studentId, String name, int age, String className) {
        this.studentId = studentId;
        this.name = name;
        this.age = age;
        this.className = className;
    }
    
    // 各种方法
    public void addScore(double score) {
        if (score >= 0 && score <= 100) {
            scores.add(score);
        }
    }
    
    public double calculateAverage() {
        if (scores.isEmpty()) {
            return 0;
        }
        
        double sum = 0;
        for (double score : scores) {
            sum += score;
        }
        return sum / scores.size();
    }
    
    public String getGrade() {
        double average = calculateAverage();
        if (average >= 90) return "A";
        else if (average >= 80) return "B";
        else if (average >= 70) return "C";
        else if (average >= 60) return "D";
        else return "F";
    }
    
    // 静态方法
    public static int getTotalStudents() {
        return totalStudents;
    }
    
    // 重写toString方法
    @Override
    public String toString() {
        return String.format("学号: %d, 姓名: %s, 年龄: %d, 班级: %s, 平均分: %.2f, 等级: %s",
                studentId, name, age, className, calculateAverage(), getGrade());
    }
    
    // getter和setter方法
    public int getStudentId() {
        return studentId;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
    
    public String getClassName() {
        return className;
    }
    
    public void setClassName(String className) {
        this.className = className;
    }
    
    public List<Double> getScores() {
        return new ArrayList<>(scores); // 返回副本,保护原始数据
    }
}

// 使用示例
class StudentManagementSystem {
    public static void main(String[] args) {
        // 创建学生对象
        Student student1 = new Student(1001, "张三", 20, "计算机1班");
        Student student2 = new Student(1002, "李四", 21, "计算机2班");
        
        // 添加成绩
        student1.addScore(85);
        student1.addScore(92);
        student1.addScore(78);
        
        student2.addScore(90);
        student2.addScore(88);
        student2.addScore(95);
        
        // 显示学生信息
        System.out.println(student1);
        System.out.println(student2);
        
        // 显示学生总数
        System.out.println("学生总数: " + Student.getTotalStudents());
    }
}

不可变类

// 不可变类示例
public final class ImmutablePerson {
    private final String name;
    private final int age;
    private final List<String> hobbies;
    
    public ImmutablePerson(String name, int age, List<String> hobbies) {
        this.name = name;
        this.age = age;
        // 防御性拷贝
        this.hobbies = new ArrayList<>(hobbies);
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public List<String> getHobbies() {
        // 返回不可修改的列表
        return Collections.unmodifiableList(hobbies);
    }
}

总结

Java普通类的核心:

  1. 封装性:通过访问修饰符控制成员的可见性
  2. 构造方法:对象初始化,支持重载
  3. 成员方法:实现类的行为,支持重载
  4. 静态成员:类级别的变量和方法
  5. 代码块:初始化代码的执行
  6. this关键字:引用当前对象
  7. 包管理:组织类和命名空间

内部类

内部类(Inner Class)是定义在另一个类内部的类。Java 提供了四种类型的内部类:

  1. 成员内部类(Member Inner Class)
  2. 静态内部类(Static Nested Class)
  3. 局部内部类(Local Inner Class)
  4. 匿名内部类(Anonymous Inner Class)

成员内部类

成员内部类是最普通的内部类,它定义在外部类的内部,就像外部类的一个成员。

public class OuterClass {
    private String outerField = "外部类字段";
    
    // 成员内部类
    class InnerClass {
        private String innerField = "内部类字段";
        
        public void display() {
            // 内部类可以直接访问外部类的私有成员
            System.out.println("访问外部类字段: " + outerField);
            System.out.println("访问内部类字段: " + innerField);
        }
    }
    
    public void createInner() {
        InnerClass inner = new InnerClass();
        inner.display();
    }
}

实例化方式

public class Test {
    public static void main(String[] args) {
        // 方式1:通过外部类实例创建内部类实例
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner1 = outer.new InnerClass();
        
        // 方式2:在外部类内部创建(推荐)
        outer.createInner();
    }
}

访问外部类成员

public class OuterClass {
    private String message = "Hello";
    
    class InnerClass {
        private String message = "World";
        
        public void showMessages() {
            System.out.println("内部类message: " + this.message);
            System.out.println("外部类message: " + OuterClass.this.message);
        }
    }
}

静态内部类

静态内部类使用 static 修饰,它不能直接访问外部类的非静态成员。

public class OuterClass {
    private String instanceField = "实例字段";
    private static String staticField = "静态字段";
    
    // 静态内部类
    static class StaticInnerClass {
        public void display() {
            // 可以访问外部类的静态成员
            System.out.println("静态字段: " + staticField);
            
            // 不能直接访问外部类的实例成员
            // System.out.println(instanceField); // 编译错误
        }
        
        public static void staticMethod() {
            System.out.println("静态内部类的静态方法");
        }
    }
}

实例化方式

public class Test {
    public static void main(String[] args) {
        // 静态内部类不需要外部类实例
        OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
        staticInner.display();
        
        // 调用静态内部类的静态方法
        OuterClass.StaticInnerClass.staticMethod();
    }
}

局部内部类

局部内部类定义在方法或作用域内,只在定义它的块中可见。

public class OuterClass {
    private String outerField = "外部字段";
    
    public void methodWithLocalClass() {
        final String localVar = "局部变量";
        
        // 局部内部类
        class LocalInnerClass {
            private String innerField = "局部内部类字段";
            
            public void display() {
                System.out.println("外部字段: " + outerField);
                System.out.println("局部变量: " + localVar); // 只能访问final或等效final的局部变量
                System.out.println("内部字段: " + innerField);
            }
        }
        
        // 在方法内部使用局部内部类
        LocalInnerClass local = new LocalInnerClass();
        local.display();
    }
    
    public void anotherMethod() {
        // 这里不能访问 LocalInnerClass,因为它在另一个方法的作用域内
    }
}

访问局部变量的限制

public class OuterClass {
    public void demonstrateFinal() {
        int normalVar = 10;
        final int finalVar = 20;
        
        // Java 8+ 中,等效final的变量也可以访问
        int effectivelyFinal = 30;
        
        class LocalClass {
            public void show() {
                // System.out.println(normalVar); // 编译错误:必须为final或等效final
                System.out.println(finalVar);     // 可以访问
                System.out.println(effectivelyFinal); // 可以访问(等效final)
            }
        }
        
        // normalVar = 100; // 如果取消注释,effectivelyFinal就不再是等效final
        new LocalClass().show();
    }
}

匿名内部类

匿名内部类没有类名,通常用于实现接口或继承类。

// 接口定义
interface Greeting {
    void sayHello(String name);
}

// 抽象类定义
abstract class Animal {
    abstract void makeSound();
}

public class AnonymousClassExample {
    public void demonstrateAnonymousClasses() {
        // 实现接口的匿名内部类
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello(String name) {
                System.out.println("Hello, " + name + "!");
            }
        };
        
        // 继承抽象类的匿名内部类
        Animal animal = new Animal() {
            @Override
            void makeSound() {
                System.out.println("Anonymous animal makes sound!");
            }
            
            // 可以添加额外的方法,但只能通过匿名类内部访问
            public void extraMethod() {
                System.out.println("Extra method");
            }
        };
        
        greeting.sayHello("World");
        animal.makeSound();
        // animal.extraMethod(); // 编译错误,Animal类型没有这个方法
    }
}

在方法参数中使用

public class AnonymousClassInMethod {
    public void process(Runnable task) {
        new Thread(task).start();
    }
    
    public void demonstrate() {
        // 匿名内部类作为方法参数
        process(new Runnable() {
            @Override
            public void run() {
                System.out.println("Running in anonymous class");
            }
        });
        
        // Java 8+ 可以使用lambda表达式替代
        process(() -> System.out.println("Running with lambda"));
    }
}

内部类的特殊特性

多重嵌套

public class MultiLevelNesting {
    class Level1 {
        class Level2 {
            class Level3 {
                public void showLevel() {
                    System.out.println("三级嵌套内部类");
                }
            }
        }
    }
    
    public void test() {
        Level1.Level2.Level3 level3 = new Level1().new Level2().new Level3();
        level3.showLevel();
    }
}

内部类继承

public class OuterForInheritance {
    class Inner {
        protected String value = "Inner value";
    }
}

class SubClass extends OuterForInheritance.Inner {
    // 需要提供外部类引用
    public SubClass(OuterForInheritance outer) {
        outer.super(); // 调用外部类的super()
    }
    
    public void show() {
        System.out.println("Value: " + value);
    }
}

接口中的内部类

interface InterfaceWithInnerClass {
    void interfaceMethod();
    
    // 接口中的内部类默认是static和public的
    class InnerClassInInterface {
        public void helperMethod() {
            System.out.println("Helper method in interface inner class");
        }
    }
}

public class TestInterfaceInner {
    public static void main(String[] args) {
        InterfaceWithInnerClass.InnerClassInInterface helper = 
            new InterfaceWithInnerClass.InnerClassInInterface();
        helper.helperMethod();
    }
}

内部类的应用

迭代器模式

import java.util.Iterator;

public class CustomCollection<T> implements Iterable<T> {
    private T[] elements;
    private int size;
    
    public CustomCollection(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }
    
    public void add(T element) {
        if (size < elements.length) {
            elements[size++] = element;
        }
    }
    
    @Override
    public Iterator<T> iterator() {
        return new CustomIterator();
    }
    
    // 内部类实现迭代器
    private class CustomIterator implements Iterator<T> {
        private int currentIndex = 0;
        
        @Override
        public boolean hasNext() {
            return currentIndex < size;
        }
        
        @Override
        public T next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException();
            }
            return elements[currentIndex++];
        }
        
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}

回调机制

public class Button {
    private ClickListener clickListener;
    
    // 内部接口
    public interface ClickListener {
        void onClick();
    }
    
    public void setClickListener(ClickListener listener) {
        this.clickListener = listener;
    }
    
    public void click() {
        if (clickListener != null) {
            clickListener.onClick();
        }
    }
}

public class GUIApplication {
    public static void main(String[] args) {
        Button button = new Button();
        
        // 使用匿名内部类实现回调
        button.setClickListener(new Button.ClickListener() {
            @Override
            public void onClick() {
                System.out.println("按钮被点击了!");
            }
        });
        
        button.click();
    }
}

内部类的内存管理和注意事项

内存泄漏风险

public class MemoryLeakExample {
    private byte[] largeData = new byte[1024 * 1024]; // 1MB
    
    class InnerClass {
        public void holdReference() {
            System.out.println("持有外部类引用");
        }
    }
    
    public InnerClass getInner() {
        return new InnerClass();
    }
    
    public static void main(String[] args) {
        MemoryLeakExample outer = new MemoryLeakExample();
        Object inner = outer.getInner();
        
        outer = null; // 外部类实例不会被GC,因为内部类持有引用
        
        // 解决方案:使用静态内部类或者弱引用
    }
}

序列化问题

import java.io.Serializable;

public class SerializationExample implements Serializable {
    private String data = "重要数据";
    
    // 内部类要实现序列化需要显式实现Serializable
    class InnerClass implements Serializable {
        private String innerData = "内部数据";
    }
}

内部类编译与普通类编译

编译后生成的类文件

普通类的编译

// 普通类
public class NormalClass {
    private String field;
    
    public void method() {
        System.out.println("Normal method");
    }
}

编译结果:

NormalClass.class

内部类的编译

public class OuterClass {
    private String outerField;
    
    // 成员内部类
    class MemberInner {
        private String innerField;
    }
    
    // 静态内部类
    static class StaticInner {
        private String staticField;
    }
    
    public void method() {
        // 局部内部类
        class LocalInner {
            private String localField;
        }
        
        // 匿名内部类
        Runnable anonymous = new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonymous");
            }
        };
    }
}

编译结果:

OuterClass.class
OuterClass$MemberInner.class
OuterClass$StaticInner.class
OuterClass$1LocalInner.class    // 局部内部类
OuterClass$1.class              // 匿名内部类

字节码结构差异

访问外部类字段的机制

源代码:

public class Outer {
    private String outerField = "outer";
    
    class Inner {
        public void accessOuter() {
            System.out.println(outerField);
        }
    }
}

编译后的字节码分析:

// 反编译 Outer$Inner.class 可以看到:
class Outer$Inner {
    // 编译器自动添加的final引用指向外部类实例
    private final Outer this$0;
    
    // 编译器生成的构造函数
    Outer$Inner(Outer outer) {
        this.this$0 = outer;
        super();
    }
    
    public void accessOuter() {
        // 通过合成引用访问外部类字段
        System.out.println(this$0.outerField);
    }
}

实际编译过程验证

让我们创建一个测试类来验证:

测试类:

// Outer.java
public class Outer {
    private int outerValue = 10;
    
    public class Inner {
        private int innerValue = 20;
        
        public int sum() {
            return outerValue + innerValue;
        }
    }
    
    public static class StaticInner {
        private int staticValue = 30;
    }
}

编译和反编译验证:

# 编译
javac Outer.java

# 查看生成的类文件
ls *.class
# Outer.class, Outer$Inner.class, Outer$StaticInner.class

# 使用javap查看字节码
javap -c Outer
javap -c Outer\$Inner
javap -c Outer\$StaticInner

构造函数差异

普通类的构造函数

public class NormalClass {
    public NormalClass() {
        // 默认构造函数
    }
    
    public NormalClass(String param) {
        // 带参数构造函数
    }
}

编译后:

  • 构造函数保持原样

内部类的构造函数

public class Outer {
    private String outerField;
    
    class Inner {
        // 看起来无参的构造函数
        Inner() {
            System.out.println("Inner constructor");
        }
    }
}

实际编译结果:

// 反编译后的Inner类
class Outer$Inner {
    private final Outer this$0;
    
    // 编译器添加了外部类参数
    Outer$Inner(Outer outer) {
        this.this$0 = outer;
        super();
        System.out.println("Inner constructor");
    }
}

访问控制差异

访问私有成员

public class Outer {
    private String privateField = "private";
    
    class Inner {
        public void accessPrivate() {
            // 内部类可以直接访问外部类的私有成员
            System.out.println(privateField);
        }
    }
}

编译处理:
编译器会为外部类生成合成访问方法(synthetic accessor methods):

// 实际编译时,编译器会为Outer类生成:
class Outer {
    private String privateField = "private";
    
    // 编译器生成的合成访问方法
    static String access$000(Outer obj) {
        return obj.privateField;
    }
}

// Inner类实际调用的是:
class Outer$Inner {
    public void accessPrivate() {
        System.out.println(Outer.access$000(this$0));
    }
}

局部内部类和匿名内部类的特殊处理

局部内部类访问局部变量

public class Outer {
    public void method() {
        final String localVar = "local";
        int effectivelyFinal = 42;
        
        class LocalInner {
            public void print() {
                System.out.println(localVar + effectivelyFinal);
            }
        }
    }
}

编译处理:

// 编译器生成的LocalInner类
class Outer$1LocalInner {
    // 编译器添加的final字段保存局部变量的副本
    private final String val$localVar;
    private final int val$effectivelyFinal;
    private final Outer this$0;
    
    // 构造函数接收所有需要访问的局部变量
    Outer$1LocalInner(Outer outer, String param1, int param2) {
        this.this$0 = outer;
        this.val$localVar = param1;
        this.val$effectivelyFinal = param2;
        super();
    }
    
    public void print() {
        System.out.println(val$localVar + val$effectivelyFinal);
    }
}

匿名内部类

public class Outer {
    public void method() {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Running");
            }
        };
    }
}

编译结果:

Outer$1.class  // 匿名内部类文件

反编译结果:

// Outer$1.class
final class Outer$1 implements Runnable {
    private final Outer this$0;
    
    Outer$1(Outer outer) {
        this.this$0 = outer;
        super();
    }
    
    @Override
    public void run() {
        System.out.println("Running");
    }
}

静态内部类的特殊处理

静态内部类不持有外部类引用

public class Outer {
    private static String staticField = "static";
    private String instanceField = "instance";
    
    static class StaticInner {
        public void access() {
            System.out.println(staticField);  // 可以访问
            // System.out.println(instanceField); // 编译错误
        }
    }
}

编译特点:

  • 不生成 this$0 字段
  • 可以直接访问外部类的静态成员
  • 编译为独立的类文件

实际编译验证

测试代码:

// CompileTest.java
public class CompileTest {
    private String instanceField = "instance";
    private static String staticField = "static";
    
    // 成员内部类
    class MemberInner {
        void access() {
            System.out.println(instanceField + staticField);
        }
    }
    
    // 静态内部类
    static class StaticInner {
        void access() {
            System.out.println(staticField);
        }
    }
    
    public void testLocal() {
        final String local = "local";
        
        // 局部内部类
        class LocalInner {
            void access() {
                System.out.println(local + instanceField);
            }
        }
        
        // 匿名内部类
        Runnable anonymous = new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonymous: " + instanceField);
            }
        };
    }
}

编译验证步骤:

# 编译
javac CompileTest.java

# 查看所有生成的类文件
ls -la *.class

# 使用javap分析字节码
javap -v CompileTest
javap -v CompileTest\$MemberInner
javap -v CompileTest\$StaticInner  
javap -v 'CompileTest$1LocalInner'
javap -v 'CompileTest$1'

编译优化的影响

合成方法和字段

编译器会生成以下合成元素:

  • this$0:成员内部类持有外部类实例的引用
  • val$localVar:局部内部类持有局部变量的副本
  • access$000():访问私有成员的合成方法

调试信息

内部类的调试信息包含:

  • 特殊的命名规则
  • 行号映射
  • 源文件关联

主要区别

特性 普通类 内部类
类文件命名 ClassName.class OuterClass$InnerClass.class
外部类引用 自动添加 this$0 字段
构造函数 保持原样 自动添加外部类参数
访问控制 正常访问规则 可访问外部类私有成员
局部变量访问 不适用 通过合成字段保存副本
静态上下文 正常 静态内部类不持有外部引用
内存占用 独立 成员内部类依赖外部实例

抽象类 (Abstract Class)

抽象类的定义和基本概念

抽象类定义语法

[访问修饰符] abstract class 类名 [extends 父类] [implements 接口1, 接口2, ...] {
    // 成员变量
    // 构造方法
    // 抽象方法
    // 具体方法
    // 代码块
    // 内部类
}

抽象类的基本特征

// 抽象类不能被实例化
public abstract class Animal {
    // 抽象方法:没有方法体,必须由子类实现
    public abstract void makeSound();
    
    // 具体方法:有方法体,子类可以直接使用或重写
    public void sleep() {
        System.out.println("动物正在睡觉...");
    }
    
    // 可以有成员变量
    protected String name;
    protected int age;
    
    // 可以有构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

抽象方法

抽象方法的特点

public abstract class Shape {
    // 抽象方法:使用abstract关键字,没有方法体
    public abstract double calculateArea();
    public abstract double calculatePerimeter();
    
    // 错误示例:抽象方法不能有方法体
    // public abstract void wrongMethod() { } // 编译错误
    
    // 抽象方法不能是private的
    // private abstract void privateAbstractMethod(); // 编译错误
    
    // 抽象方法不能是static的
    // public static abstract void staticAbstractMethod(); // 编译错误
    
    // 抽象方法不能是final的
    // public final abstract void finalAbstractMethod(); // 编译错误
}

抽象方法的访问修饰符

public abstract class AccessModifierExample {
    // public抽象方法 - 最常见
    public abstract void publicAbstractMethod();
    
    // protected抽象方法 - 子类或同包可见
    protected abstract void protectedAbstractMethod();
    
    // 默认修饰符抽象方法 - 同包可见
    abstract void defaultAbstractMethod();
    
    // private抽象方法不允许
    // private abstract void privateAbstractMethod(); // 编译错误
}

抽象类构造方法的使用

public abstract class Vehicle {
    protected String brand;
    protected String model;
    protected int year;
    
    // 抽象类可以有构造方法
    public Vehicle(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        System.out.println("Vehicle构造方法被调用");
    }
    
    // 可以有多个构造方法
    public Vehicle(String brand) {
        this(brand, "未知型号", 2020);
    }
    
    public abstract void start();
    public abstract void stop();
}

// 子类必须调用父类的构造方法
class Car extends Vehicle {
    private int doorCount;
    
    public Car(String brand, String model, int year, int doorCount) {
        super(brand, model, year); // 必须调用父类构造方法
        this.doorCount = doorCount;
    }
    
    @Override
    public void start() {
        System.out.println(brand + " " + model + " 汽车启动");
    }
    
    @Override
    public void stop() {
        System.out.println(brand + " " + model + " 汽车停止");
    }
}

抽象类的成员变量

public abstract class MemberVariableExample {
    // 实例变量
    protected String instanceVar = "实例变量";
    
    // 静态变量
    public static String staticVar = "静态变量";
    
    // 常量
    public static final String CONSTANT_VAR = "常量";
    
    // 瞬态变量
    protected transient String transientVar;
    
    // volatile 变量
    protected volatile boolean flag;
    
    // final变量
    protected final String finalVar;
    
    public MemberVariableExample() {
        this.finalVar = "最终变量"; // 必须在构造方法中初始化final变量
    }
}

抽象类的具体方法

public abstract class ConcreteMethodExample {
    // 普通具体方法
    public void normalMethod() {
        System.out.println("这是一个普通具体方法");
    }
    
    // final方法 - 子类不能重写
    public final void finalMethod() {
        System.out.println("这是一个final方法");
    }
    
    // static方法
    public static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
    
    // private方法
    private void privateMethod() {
        System.out.println("这是一个私有方法");
    }
    
    // protected方法
    protected void protectedMethod() {
        System.out.println("这是一个受保护方法");
    }
    
    // 模板方法模式示例
    public final void templateMethod() {
        step1();
        step2();
        step3();
        hookMethod(); // 钩子方法
    }
    
    private void step1() {
        System.out.println("步骤1");
    }
    
    private void step2() {
        System.out.println("步骤2");
    }
    
    // 抽象方法,由子类实现
    protected abstract void step3();
    
    // 钩子方法,子类可以选择性重写
    protected void hookMethod() {
        // 默认空实现
    }
}

抽象类的继承

抽象类继承抽象类

当一个抽象类继承另一个抽象类时,可以:

  • 实现部分父类的抽象方法
  • 保持其他抽象方法不变
  • 添加新的抽象方法

这种设计允许在继承链中:

  1. 提供通用实现(如所有哺乳动物睡觉方式相似)
  2. 强制特定实现(如不同动物吃的方式不同)
  3. 逐步具体化,减少代码重复

这就是面向对象设计中"抽象层次逐步具体化"的典型应用

public abstract class AbstractAnimal {
    protected String name;
    
    public AbstractAnimal(String name) {
        this.name = name;
    }
    
    public abstract void eat();
    public abstract void sleep();
}

// 抽象类继承另一个抽象类
public abstract class AbstractMammal extends AbstractAnimal {
    protected boolean hasFur;
    
    public AbstractMammal(String name, boolean hasFur) {
        super(name);
        this.hasFur = hasFur;
    }
    
    // 可以实现部分抽象方法
    @Override
    public void sleep() {
        System.out.println(name + " 正在睡觉");
    }
    
    // 可以添加新的抽象方法
    public abstract void giveBirth();
    
    // eat方法仍然保持抽象,由具体子类实现
}

// 具体类继承抽象类
class Dog extends AbstractMammal {
    public Dog(String name, boolean hasFur) {
        super(name, hasFur);
    }
    
    @Override
    public void eat() {
        System.out.println(name + " 在吃狗粮");
    }
    
    @Override
    public void giveBirth() {
        System.out.println(name + " 生小狗");
    }
}

必须实现所有抽象方法

public abstract class IncompleteAbstractClass {
    public abstract void method1();
    public abstract void method2();
}

// 错误示例:没有实现所有抽象方法
// class ConcreteClass1 extends IncompleteAbstractClass { // 编译错误
//     @Override
//     public void method1() { }
//     // 缺少method2的实现
// }

// 正确示例:实现所有抽象方法
class ConcreteClass2 extends IncompleteAbstractClass {
    @Override
    public void method1() {
        System.out.println("实现method1");
    }
    
    @Override
    public void method2() {
        System.out.println("实现method2");
    }
}

抽象类实现接口

interface Flyable {
    void fly();
    void land();
}

interface Swimmable {
    void swim();
    void dive();
}

// 抽象类实现接口
public abstract class Bird implements Flyable {
    protected String name;
    protected double wingspan;
    
    public Bird(String name, double wingspan) {
        this.name = name;
        this.wingspan = wingspan;
    }
    
    // 实现部分接口方法
    @Override
    public void land() {
        System.out.println(name + " 正在降落");
    }
    
    // fly方法保持抽象,由具体子类实现
    // public abstract void fly(); // 隐式存在
    
    // 可以添加自己的抽象方法
    public abstract void buildNest();
}

// 实现多个接口
public abstract class Duck implements Flyable, Swimmable {
    protected String name;
    
    public Duck(String name) {
        this.name = name;
    }
    
    // 必须实现所有接口的抽象方法,或者声明为抽象
    @Override
    public abstract void fly();
    
    @Override
    public abstract void land();
    
    @Override
    public abstract void swim();
    
    @Override
    public abstract void dive();
}

// 具体实现
class MallardDuck extends Duck {
    public MallardDuck(String name) {
        super(name);
    }
    
    @Override
    public void fly() {
        System.out.println(name + " 在飞行");
    }
    
    @Override
    public void land() {
        System.out.println(name + " 降落在水面上");
    }
    
    @Override
    public void swim() {
        System.out.println(name + " 在游泳");
    }
    
    @Override
    public void dive() {
        System.out.println(name + " 在潜水");
    }
}

经典模板方法模式

public abstract class DataProcessor {
    // 模板方法 - 定义算法骨架
    public final void process() {
        readData();
        processData();
        writeData();
        if (needValidation()) {
            validateData();
        }
    }
    
    // 具体方法
    private void readData() {
        System.out.println("读取数据...");
    }
    
    private void writeData() {
        System.out.println("写入数据...");
    }
    
    // 抽象方法 - 由子类实现
    protected abstract void processData();
    
    // 钩子方法 - 子类可以选择性重写
    protected boolean needValidation() {
        return false;
    }
    
    protected void validateData() {
        System.out.println("验证数据...");
    }
}

// 具体实现
class CSVProcessor extends DataProcessor {
    @Override
    protected void processData() {
        System.out.println("处理CSV数据...");
    }
    
    @Override
    protected boolean needValidation() {
        return true;
    }
    
    @Override
    protected void validateData() {
        System.out.println("验证CSV数据格式...");
    }
}

class XMLProcessor extends DataProcessor {
    @Override
    protected void processData() {
        System.out.println("处理XML数据...");
    }
}

复杂示例:图形系统

import java.awt.Color;

public abstract class GraphicObject {
    // 成员变量
    protected int x, y;
    protected Color color;
    protected boolean visible;
    
    // 静态变量
    protected static int objectCount = 0;
    
    // 构造方法
    public GraphicObject(int x, int y, Color color) {
        this.x = x;
        this.y = y;
        this.color = color;
        this.visible = true;
        objectCount++;
    }
    
    // 抽象方法
    public abstract void draw();
    public abstract void resize(double scale);
    public abstract double calculateArea();
    public abstract double calculatePerimeter();
    
    // 具体方法
    public void move(int newX, int newY) {
        this.x = newX;
        this.y = newY;
        System.out.println("图形移动到 (" + x + ", " + y + ")");
    }
    
    public void setColor(Color newColor) {
        this.color = newColor;
        System.out.println("颜色已更改");
    }
    
    public void show() {
        this.visible = true;
        System.out.println("图形显示");
    }
    
    public void hide() {
        this.visible = false;
        System.out.println("图形隐藏");
    }
    
    // final方法
    public final String getPosition() {
        return "(" + x + ", " + y + ")";
    }
    
    // 静态方法
    public static int getObjectCount() {
        return objectCount;
    }
    
    // 模板方法
    public final void render() {
        if (visible) {
            System.out.println("开始渲染图形...");
            draw();
            System.out.println("图形渲染完成");
        } else {
            System.out.println("图形不可见,跳过渲染");
        }
    }
}

// 具体实现 - 圆形
class Circle extends GraphicObject {
    private double radius;
    
    public Circle(int x, int y, Color color, double radius) {
        super(x, y, color);
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制圆形: 中心(" + x + ", " + y + "), 半径=" + radius + ", 颜色=" + color);
    }
    
    @Override
    public void resize(double scale) {
        this.radius *= scale;
        System.out.println("圆形缩放,新半径: " + radius);
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
    
    // 特有的方法
    public double getDiameter() {
        return 2 * radius;
    }
}

// 具体实现 - 矩形
class Rectangle extends GraphicObject {
    private double width, height;
    
    public Rectangle(int x, int y, Color color, double width, double height) {
        super(x, y, color);
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制矩形: 左上角(" + x + ", " + y + "), 宽=" + width + ", 高=" + height + ", 颜色=" + color);
    }
    
    @Override
    public void resize(double scale) {
        this.width *= scale;
        this.height *= scale;
        System.out.println("矩形缩放,新尺寸: " + width + "x" + height);
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * (width + height);
    }
    
    // 特有的方法
    public boolean isSquare() {
        return width == height;
    }
}

抽象类的设计模式 - 工厂方法模式

public abstract class Document {
    protected String title;
    protected String content;
    
    public Document(String title) {
        this.title = title;
    }
    
    // 抽象工厂方法
    public abstract void create();
    public abstract void save();
    public abstract void print();
    
    // 模板方法
    public final void processDocument() {
        create();
        edit();
        save();
        print();
    }
    
    // 钩子方法
    protected void edit() {
        System.out.println("编辑文档: " + title);
    }
}

// 具体文档类型
class WordDocument extends Document {
    public WordDocument(String title) {
        super(title);
    }
    
    @Override
    public void create() {
        System.out.println("创建Word文档: " + title);
        this.content = "Word文档内容";
    }
    
    @Override
    public void save() {
        System.out.println("保存Word文档为 .docx 格式");
    }
    
    @Override
    public void print() {
        System.out.println("打印Word文档");
    }
    
    @Override
    protected void edit() {
        super.edit();
        System.out.println("使用Word特定功能编辑");
    }
}

class PDFDocument extends Document {
    public PDFDocument(String title) {
        super(title);
    }
    
    @Override
    public void create() {
        System.out.println("创建PDF文档: " + title);
        this.content = "PDF文档内容";
    }
    
    @Override
    public void save() {
        System.out.println("保存PDF文档为 .pdf 格式");
    }
    
    @Override
    public void print() {
        System.out.println("打印PDF文档(优化打印质量)");
    }
}

选择抽象类的情况

// 适合使用抽象类的场景:

// 1. 需要共享代码
public abstract class DatabaseService {
    protected Connection connection;
    
    // 共享的具体方法
    protected void connect(String url, String username, String password) {
        System.out.println("连接到数据库: " + url);
        // 连接逻辑...
    }
    
    protected void disconnect() {
        System.out.println("断开数据库连接");
        // 断开逻辑...
    }
    
    // 抽象方法
    public abstract void executeQuery(String query);
    public abstract void createTable(String tableName);
}

// 2. 需要定义模板方法
public abstract class Game {
    // 模板方法
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
    
    protected abstract void initialize();
    protected abstract void startPlay();
    protected abstract void endPlay();
}

// 3. 需要维护状态
public abstract class StatefulComponent {
    protected State currentState;
    protected List<State> stateHistory;
    
    public StatefulComponent() {
        this.stateHistory = new ArrayList<>();
    }
    
    public abstract void transitionTo(State newState);
    public abstract boolean isValidTransition(State newState);
}

设计原则

// 1. 合理设计抽象级别
public abstract class PaymentProcessor {
    protected double amount;
    protected String currency;
    
    public PaymentProcessor(double amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
    
    // 适度的抽象 - 所有支付方式都需要的方法
    public abstract boolean validatePayment();
    public abstract String processPayment();
    public abstract String getPaymentMethod();
    
    // 具体方法 - 共享逻辑
    protected final String formatAmount() {
        return String.format("%.2f %s", amount, currency);
    }
    
    // 模板方法
    public final String executePayment() {
        if (validatePayment()) {
            return processPayment();
        } else {
            return "支付验证失败";
        }
    }
}

// 2. 避免过度抽象
public abstract class SimpleAbstractClass {
    // 好的抽象:有明确的抽象目的
    public abstract void performAction();
    
    // 避免:只有一个抽象方法的抽象类,考虑使用接口
    // public abstract void singleMethod();
}

总结

Java抽象类的核心要点:

  1. 定义:使用abstract关键字,不能实例化
  2. 抽象方法:没有方法体,必须由子类实现
  3. 构造方法:可以有,用于子类初始化
  4. 具体方法:可以有实现的方法
  5. 继承规则:必须实现所有抽象方法,或者声明为抽象类
  6. 设计模式:常用于模板方法模式、工厂方法模式等
  7. 与接口比较:适合共享代码、维护状态、定义模板方法的场景

接口 (Interface)

接口的定义和基本概念

接口定义语法

[访问修饰符] interface 接口名 [extends 父接口1, 父接口2, ...] {
    // 常量
    // 抽象方法
    // 默认方法 (Java 8+)
    // 静态方法 (Java 8+)
    // 私有方法 (Java 9+)
}

接口的基本特征

// 基本接口定义
public interface Animal {
    // 常量 (默认是 public static final)
    String KINGDOM = "Animalia";
    
    // 抽象方法 (默认是 public abstract)
    void makeSound();
    void eat();
    
    // 默认方法 (Java 8+)
    default void sleep() {
        System.out.println("动物正在睡觉...");
    }
    
    // 静态方法 (Java 8+)
    static void displayKingdom() {
        System.out.println("动物界: " + KINGDOM);
    }
}

接口的常量定义和特点

public interface ConstantsExample {
    // 以下三种定义方式是等价的
    int MAX_SIZE = 100;                    // 默认 public static final
    public static final int MIN_SIZE = 1;  // 显式声明
    public int DEFAULT_SIZE = 10;          // 省略 static final
    
    // 复杂常量
    String[] VALID_TYPES = {"TYPE_A", "TYPE_B", "TYPE_C"};
    List<String> CATEGORIES = List.of("CAT1", "CAT2", "CAT3");
    
    // 编译时常量
    double PI = 3.14159;
    long TIMEOUT = 5000L;
}

// 使用接口常量
class ConstantUser {
    public void process() {
        System.out.println("最大尺寸: " + ConstantsExample.MAX_SIZE);
        System.out.println("默认尺寸: " + ConstantsExample.DEFAULT_SIZE);
    }
}

抽象方法的定义

public interface MethodExample {
    // 以下定义方式是等价的
    void method1();                    // 默认 public abstract
    public abstract void method2();    // 显式声明
    abstract void method3();           // 省略 public
    
    // 带参数和返回值的方法
    String getName();
    void setName(String name);
    boolean isValid(int value);
    double calculate(double x, double y);
    
    // 注意:不能有方法体
    // void wrongMethod() { } // 编译错误
}

// 实现接口
class MethodExampleImpl implements MethodExample {
    private String name;
    
    @Override
    public void method1() {
        System.out.println("实现 method1");
    }
    
    @Override
    public void method2() {
        System.out.println("实现 method2");
    }
    
    @Override
    public void method3() {
        System.out.println("实现 method3");
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public boolean isValid(int value) {
        return value > 0;
    }
    
    @Override
    public double calculate(double x, double y) {
        return x + y;
    }
}

默认方法 (Java 8+)

默认方法的定义和使用

public interface DefaultMethodExample {
    // 抽象方法
    void performAction();
    
    // 默认方法 - 有方法体
    default void logAction(String action) {
        System.out.println("执行动作: " + action);
        System.out.println("时间: " + java.time.LocalDateTime.now());
    }
    
    default String getDefaultName() {
        return "默认名称";
    }
    
    // 默认方法可以调用其他方法
    default void performWithLog() {
        logAction("开始执行");
        performAction();
        logAction("执行完成");
    }
    
    // 默认方法可以重写Object类的方法,但不推荐
    @Override
    default String toString() {
        return "DefaultMethodExample实例";
    }
}

// 实现类可以选择重写默认方法
class DefaultMethodImpl implements DefaultMethodExample {
    @Override
    public void performAction() {
        System.out.println("执行具体动作");
    }
    
    // 可选:重写默认方法
    @Override
    public String getDefaultName() {
        return "自定义名称";
    }
}

// 实现类也可以不重写默认方法
class SimpleImpl implements DefaultMethodExample {
    @Override
    public void performAction() {
        System.out.println("简单实现");
    }
    // 使用接口提供的默认方法
}

默认方法的多继承冲突

interface InterfaceA {
    default void conflictMethod() {
        System.out.println("来自 InterfaceA");
    }
}

interface InterfaceB {
    default void conflictMethod() {
        System.out.println("来自 InterfaceB");
    }
}

// 编译错误:默认方法冲突
// class ConflictClass implements InterfaceA, InterfaceB { }

// 解决方案1:重写冲突方法
class Solution1 implements InterfaceA, InterfaceB {
    @Override
    public void conflictMethod() {
        System.out.println("重写冲突方法");
        // 可以选择调用特定的接口方法
        InterfaceA.super.conflictMethod();
    }
}

// 解决方案2:选择其中一个接口
class Solution2 implements InterfaceA {
    // 使用 InterfaceA 的默认方法
}

interface InterfaceC extends InterfaceA {
    // 解决方案3:在接口中重写
    @Override
    default void conflictMethod() {
        System.out.println("InterfaceC 重写");
    }
}

静态方法 (Java 8+)

public interface StaticMethodExample {
    // 静态方法
    static String createId() {
        return "ID-" + System.currentTimeMillis();
    }
    
    static boolean isValidEmail(String email) {
        return email != null && email.contains("@");
    }
    
    static double calculateCircleArea(double radius) {
        return Math.PI * radius * radius;
    }
    
    // 静态方法可以调用其他静态方法
    static void validateAndProcess(String email) {
        if (isValidEmail(email)) {
            System.out.println("处理邮箱: " + email);
        } else {
            System.out.println("无效邮箱");
        }
    }
    
    // 抽象方法
    void instanceMethod();
}

// 使用静态方法
class StaticMethodUser {
    public void demo() {
        // 通过接口名直接调用静态方法
        String id = StaticMethodExample.createId();
        boolean valid = StaticMethodExample.isValidEmail("test@example.com");
        double area = StaticMethodExample.calculateCircleArea(5.0);
        
        System.out.println("ID: " + id);
        System.out.println("邮箱有效: " + valid);
        System.out.println("面积: " + area);
    }
}

// 实现类不能继承接口的静态方法
class StaticMethodImpl implements StaticMethodExample {
    @Override
    public void instanceMethod() {
        // 不能这样调用:this.createId(); // 错误
        // 必须通过接口名调用
        String id = StaticMethodExample.createId();
        System.out.println("使用ID: " + id);
    }
}

私有方法 (Java 9+)

public interface PrivateMethodExample {
    // 默认方法
    default void complexOperation() {
        validateInput();
        step1();
        step2();
        cleanup();
    }
    
    default void anotherOperation() {
        validateInput();
        // 其他操作...
        cleanup();
    }
    
    // 私有方法 - 辅助方法
    private void validateInput() {
        System.out.println("验证输入...");
        // 验证逻辑
    }
    
    private void step1() {
        System.out.println("执行步骤1...");
        // 步骤1逻辑
    }
    
    private void step2() {
        System.out.println("执行步骤2...");
        // 步骤2逻辑
    }
    
    private void cleanup() {
        System.out.println("清理资源...");
        // 清理逻辑
    }
    
    // 私有静态方法
    private static String generateInternalId() {
        return "INTERNAL_" + System.nanoTime();
    }
    
    static String createInternalResource() {
        String id = generateInternalId();
        System.out.println("创建资源: " + id);
        return id;
    }
}

// 实现类
class PrivateMethodImpl implements PrivateMethodExample {
    // 私有方法对实现类不可见
    // 只能使用默认方法
}

接口的继承

接口继承接口

interface BasicAnimal {
    void eat();
    void sleep();
}

interface Mammal extends BasicAnimal {
    void giveBirth();
    default void breathe() {
        System.out.println("用肺呼吸");
    }
}

interface Swimmer {
    void swim();
}

// 多重继承
interface AquaticMammal extends Mammal, Swimmer {
    void dive();
    
    @Override
    default void breathe() {
        System.out.println("浮出水面呼吸");
    }
}

// 具体实现
class Dolphin implements AquaticMammal {
    @Override
    public void eat() {
        System.out.println("吃鱼");
    }
    
    @Override
    public void sleep() {
        System.out.println("水中睡觉");
    }
    
    @Override
    public void giveBirth() {
        System.out.println("生小海豚");
    }
    
    @Override
    public void swim() {
        System.out.println("快速游泳");
    }
    
    @Override
    public void dive() {
        System.out.println("深潜");
    }
}

复杂的接口继承

interface Readable {
    String read();
    default void open() {
        System.out.println("打开资源");
    }
}

interface Writable {
    void write(String content);
    default void open() {
        System.out.println("打开写入流");
    }
}

// 解决默认方法冲突
interface ReadWritable extends Readable, Writable {
    // 必须解决 open() 方法的冲突
    @Override
    default void open() {
        System.out.println("打开读写流");
        Readable.super.open();  // 调用 Readable 的 open
        Writable.super.open();  // 调用 Writable 的 open
    }
    
    // 添加新方法
    void flush();
}

class FileProcessor implements ReadWritable {
    private String content = "";
    
    @Override
    public String read() {
        return content;
    }
    
    @Override
    public void write(String content) {
        this.content = content;
    }
    
    @Override
    public void flush() {
        System.out.println("刷新缓冲区");
    }
}

类实现多个接口

interface Flyable {
    void fly();
    default void takeOff() {
        System.out.println("起飞");
    }
}

interface Swimmable {
    void swim();
    default void dive() {
        System.out.println("潜水");
    }
}

interface Runnable {
    void run();
    default void jump() {
        System.out.println("跳跃");
    }
}

// 实现多个接口
class Duck implements Flyable, Swimmable, Runnable {
    private String name;
    
    public Duck(String name) {
        this.name = name;
    }
    
    @Override
    public void fly() {
        System.out.println(name + " 在飞行");
    }
    
    @Override
    public void swim() {
        System.out.println(name + " 在游泳");
    }
    
    @Override
    public void run() {
        System.out.println(name + " 在奔跑");
    }
    
    // 可以重写默认方法
    @Override
    public void takeOff() {
        System.out.println(name + " 从水面起飞");
    }
}

// 使用多态
class MultiInterfaceDemo {
    public static void main(String[] args) {
        Duck duck = new Duck("唐老鸭");
        
        // 作为 Flyable 使用
        Flyable flyable = duck;
        flyable.fly();
        flyable.takeOff();
        
        // 作为 Swimmable 使用
        Swimmable swimmable = duck;
        swimmable.swim();
        swimmable.dive();
        
        // 作为 Runnable 使用
        Runnable runnable = duck;
        runnable.run();
        runnable.jump();
    }
}

函数式接口

函数式接口定义

// 函数式接口:只有一个抽象方法
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
    
    // 可以有默认方法
    default void printResult(int result) {
        System.out.println("结果: " + result);
    }
    
    // 可以有静态方法
    static Calculator create() {
        return (a, b) -> a + b;
    }
    
    // 不能有第二个抽象方法
    // void anotherAbstractMethod(); // 编译错误
}

// 使用函数式接口
class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        // 使用 Lambda 表达式
        Calculator adder = (a, b) -> a + b;
        Calculator multiplier = (a, b) -> a * b;
        
        System.out.println("加法: " + adder.calculate(5, 3));
        System.out.println("乘法: " + multiplier.calculate(5, 3));
        
        // 使用方法引用
        Calculator anotherAdder = Integer::sum;
        System.out.println("另一种加法: " + anotherAdder.calculate(5, 3));
    }
}

常见的函数式接口

import java.util.function.*;

public class CommonFunctionalInterfaces {
    // Predicate - 接受一个参数,返回boolean
    Predicate<String> isLong = s -> s.length() > 5;
    
    // Function - 接受一个参数,返回一个结果
    Function<String, Integer> stringToInt = Integer::parseInt;
    
    // Consumer - 接受一个参数,没有返回值
    Consumer<String> printer = System.out::println;
    
    // Supplier - 没有参数,返回一个结果
    Supplier<Double> randomSupplier = Math::random;
    
    // UnaryOperator - 接受一个参数,返回同类型结果
    UnaryOperator<String> toupper = String::toUpperCase;
    
    // BinaryOperator - 接受两个同类型参数,返回同类型结果
    BinaryOperator<Integer> adder = Integer::sum;
    
    public void demo() {
        System.out.println("是否长字符串: " + isLong.test("Hello World"));
        System.out.println("字符串转数字: " + stringToInt.apply("123"));
        printer.accept("Hello Consumer");
        System.out.println("随机数: " + randomSupplier.get());
        System.out.println("转大写: " + toupper.apply("hello"));
        System.out.println("相加: " + adder.apply(5, 3));
    }
}

标记接口

// 标记接口:没有任何方法的接口
interface Serializable {
    // 空接口
}

interface Cloneable {
    // 空接口
}

interface Remote {
    // 空接口
}

// 自定义标记接口
interface Loggable {
    // 标记需要记录日志的类
}

interface Cacheable {
    // 标记可以缓存的类
}

// 使用标记接口
class User implements Loggable, Cacheable {
    private String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 根据标记接口执行不同逻辑
    public void process(Object obj) {
        if (obj instanceof Loggable) {
            System.out.println("记录操作日志");
        }
        
        if (obj instanceof Cacheable) {
            System.out.println("加入缓存");
        }
    }
}

复杂示例:支付系统接口设计

import java.math.BigDecimal;
import java.time.LocalDateTime;

// 支付接口
public interface Payment {
    // 常量
    BigDecimal MAX_AMOUNT = new BigDecimal("1000000");
    String DEFAULT_CURRENCY = "CNY";
    
    // 抽象方法
    String processPayment(BigDecimal amount, String currency);
    boolean validatePayment();
    String getPaymentId();
    
    // 默认方法
    default String getTimestamp() {
        return LocalDateTime.now().toString();
    }
    
    default boolean validateAmount(BigDecimal amount) {
        return amount != null && 
               amount.compareTo(BigDecimal.ZERO) > 0 && 
               amount.compareTo(MAX_AMOUNT) <= 0;
    }
    
    default String formatAmount(BigDecimal amount, String currency) {
        return String.format("%s %.2f", currency, amount);
    }
    
    // 静态方法
    static String generateTransactionId() {
        return "TXN_" + System.currentTimeMillis() + "_" + 
               (int)(Math.random() * 1000);
    }
    
    static boolean isValidCurrency(String currency) {
        return currency != null && 
               (currency.equals("CNY") || currency.equals("USD") || 
                currency.equals("EUR"));
    }
}

// 退款接口
interface Refundable extends Payment {
    String processRefund(BigDecimal amount, String reason);
    
    @Override
    default boolean validatePayment() {
        System.out.println("验证可退款支付");
        return true;
    }
}

// 国际支付接口
interface InternationalPayment extends Payment {
    double getExchangeRate(String fromCurrency, String toCurrency);
    BigDecimal calculateFee(BigDecimal amount);
    
    @Override
    default String processPayment(BigDecimal amount, String currency) {
        if (!isValidCurrency(currency)) {
            return "不支持货币: " + currency;
        }
        
        BigDecimal fee = calculateFee(amount);
        BigDecimal total = amount.add(fee);
        
        return String.format("国际支付: %s, 手续费: %s, 总计: %s",
                formatAmount(amount, currency),
                formatAmount(fee, currency),
                formatAmount(total, currency));
    }
}

// 具体实现 - 支付宝支付
class AlipayPayment implements Refundable {
    private String paymentId;
    
    public AlipayPayment() {
        this.paymentId = Payment.generateTransactionId();
    }
    
    @Override
    public String processPayment(BigDecimal amount, String currency) {
        if (!validateAmount(amount)) {
            return "金额无效";
        }
        
        if (!isValidCurrency(currency)) {
            return "货币无效";
        }
        
        return String.format("支付宝支付成功: ID=%s, 金额=%s, 时间=%s",
                paymentId, formatAmount(amount, currency), getTimestamp());
    }
    
    @Override
    public boolean validatePayment() {
        System.out.println("验证支付宝支付");
        return true;
    }
    
    @Override
    public String getPaymentId() {
        return paymentId;
    }
    
    @Override
    public String processRefund(BigDecimal amount, String reason) {
        return String.format("支付宝退款: 金额=%s, 原因=%s, 时间=%s",
                formatAmount(amount, DEFAULT_CURRENCY), reason, getTimestamp());
    }
}

// 具体实现 - PayPal支付
class PayPalPayment implements InternationalPayment {
    private String paymentId;
    
    public PayPalPayment() {
        this.paymentId = Payment.generateTransactionId();
    }
    
    @Override
    public String processPayment(BigDecimal amount, String currency) {
        // 使用接口的默认实现
        String result = InternationalPayment.super.processPayment(amount, currency);
        return "PayPal " + result;
    }
    
    @Override
    public boolean validatePayment() {
        System.out.println("验证PayPal支付");
        return true;
    }
    
    @Override
    public String getPaymentId() {
        return paymentId;
    }
    
    @Override
    public double getExchangeRate(String fromCurrency, String toCurrency) {
        // 模拟汇率
        if ("USD".equals(fromCurrency) && "CNY".equals(toCurrency)) {
            return 6.5;
        }
        return 1.0;
    }
    
    @Override
    public BigDecimal calculateFee(BigDecimal amount) {
        // 手续费为金额的3.5%
        return amount.multiply(new BigDecimal("0.035"));
    }
}

接口与策略模式

// 策略接口
interface SortingStrategy {
    void sort(int[] array);
    default void printArray(int[] array) {
        for (int num : array) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

// 具体策略
class BubbleSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        System.out.println("使用冒泡排序");
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }
}

class QuickSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        System.out.println("使用快速排序");
        quickSort(array, 0, array.length - 1);
    }
    
    private void quickSort(int[] array, int low, int high) {
        if (low < high) {
            int pivot = partition(array, low, high);
            quickSort(array, low, pivot - 1);
            quickSort(array, pivot + 1, high);
        }
    }
    
    private int partition(int[] array, int low, int high) {
        int pivot = array[high];
        int i = low - 1;
        for (int j = low; j < high; j++) {
            if (array[j] <= pivot) {
                i++;
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        int temp = array[i + 1];
        array[i + 1] = array[high];
        array[high] = temp;
        return i + 1;
    }
}

// 上下文类
class Sorter {
    private SortingStrategy strategy;
    
    public Sorter(SortingStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void setStrategy(SortingStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void sortArray(int[] array) {
        System.out.println("排序前:");
        strategy.printArray(array);
        
        strategy.sort(array);
        
        System.out.println("排序后:");
        strategy.printArray(array);
    }
}

接口设计原则

// 1. 接口隔离原则 - 多个专用接口优于一个通用接口
interface Printer {
    void print();
}

interface Scanner {
    void scan();
}

interface Fax {
    void fax();
}

// 而不是一个大的接口
// interface AllInOne { void print(); void scan(); void fax(); }

// 2. 依赖倒置原则 - 依赖于抽象而不是具体
interface DataService {
    String fetchData();
}

class DatabaseService implements DataService {
    @Override
    public String fetchData() {
        return "数据库数据";
    }
}

class ApiService implements DataService {
    @Override
    public String fetchData() {
        return "API数据";
    }
}

class BusinessLogic {
    private DataService dataService;
    
    public BusinessLogic(DataService dataService) {
        this.dataService = dataService; // 依赖于抽象
    }
    
    public void process() {
        String data = dataService.fetchData();
        System.out.println("处理: " + data);
    }
}

总结

Java接口的核心要点:

  1. 定义:使用interface关键字,支持多继承
  2. 常量:默认public static final
  3. 抽象方法:默认public abstract
  4. 默认方法:Java 8+,有方法体,可被重写
  5. 静态方法:Java 8+,通过接口名调用
  6. 私有方法:Java 9+,接口内部使用
  7. 函数式接口:只有一个抽象方法,支持Lambda
  8. 标记接口:没有任何方法的接口
  9. 设计模式:广泛应用于策略模式、工厂模式等

枚举 (Enum)

枚举的定义和基本概念

枚举定义语法

[访问修饰符] enum 枚举名 [implements 接口1, 接口2, ...] {
    // 枚举常量
    // 成员变量
    // 构造方法
    // 成员方法
    // 抽象方法
}

基本枚举示例

// 最简单的枚举
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

// 使用枚举
class EnumDemo {
    public static void main(String[] args) {
        Day today = Day.MONDAY;
        System.out.println("Today is: " + today);
        
        // 遍历所有枚举值
        for (Day day : Day.values()) {
            System.out.println(day);
        }
    }
}

枚举的成员变量和构造方法

public enum Planet {
    // 枚举常量,调用构造方法
    MERCURY(3.303e+23, 2.4397e6),
    VENUS(4.869e+24, 6.0518e6),
    EARTH(5.976e+24, 6.37814e6),
    MARS(6.421e+23, 3.3972e6),
    JUPITER(1.9e+27, 7.1492e7),
    SATURN(5.688e+26, 6.0268e7),
    URANUS(8.686e+25, 2.5559e7),
    NEPTUNE(1.024e+26, 2.4746e7);
    
    // 成员变量
    private final double mass;   // 质量(千克)
    private final double radius; // 半径(米)
    
    // 构造方法 - 必须是private(默认就是private,不能是public)
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    
    // 计算方法
    public double surfaceGravity() {
        final double G = 6.67300E-11; // 万有引力常数
        return G * mass / (radius * radius);
    }
    
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    
    // Getter方法
    public double getMass() {
        return mass;
    }
    
    public double getRadius() {
        return radius;
    }
}

// 使用带属性的枚举
class PlanetDemo {
    public static void main(String[] args) {
        double earthWeight = 175; // 地球上的重量(磅)
        double mass = earthWeight / Planet.EARTH.surfaceGravity();
        
        for (Planet p : Planet.values()) {
            System.out.printf("在 %s 上的重量是 %.2f 磅%n",
                    p, p.surfaceWeight(mass));
        }
    }
}

枚举的实例方法和静态方法

public enum Operation {
    PLUS, MINUS, TIMES, DIVIDE;
    
    // 实例方法
    public double calculate(double x, double y) {
        switch (this) {
            case PLUS:   return x + y;
            case MINUS:  return x - y;
            case TIMES:  return x * y;
            case DIVIDE: return x / y;
            default: throw new AssertionError("未知操作: " + this);
        }
    }
    
    // 静态方法
    public static Operation fromSymbol(String symbol) {
        switch (symbol) {
            case "+": return PLUS;
            case "-": return MINUS;
            case "*": return TIMES;
            case "/": return DIVIDE;
            default: throw new IllegalArgumentException("未知符号: " + symbol);
        }
    }
    
    // 重写toString方法
    @Override
    public String toString() {
        switch (this) {
            case PLUS:   return "+";
            case MINUS:  return "-";
            case TIMES:  return "*";
            case DIVIDE: return "/";
            default: return name();
        }
    }
}

// 使用方法
class OperationDemo {
    public static void main(String[] args) {
        double result = Operation.PLUS.calculate(10, 5);
        System.out.println("10 + 5 = " + result);
        
        Operation op = Operation.fromSymbol("*");
        System.out.println("操作符: " + op);
        System.out.println("10 * 5 = " + op.calculate(10, 5));
    }
}

枚举实现接口

// 定义接口
interface Describable {
    String getDescription();
    String getColor();
}

// 枚举实现接口
public enum TrafficLight implements Describable {
    RED("停止", "红色") {
        @Override
        public TrafficLight next() {
            return GREEN;
        }
    },
    YELLOW("警告", "黄色") {
        @Override
        public TrafficLight next() {
            return RED;
        }
    },
    GREEN("通行", "绿色") {
        @Override
        public TrafficLight next() {
            return YELLOW;
        }
    };
    
    private final String description;
    private final String color;
    
    TrafficLight(String description, String color) {
        this.description = description;
        this.color = color;
    }
    
    // 实现接口方法
    @Override
    public String getDescription() {
        return description;
    }
    
    @Override
    public String getColor() {
        return color;
    }
    
    // 抽象方法 - 每个枚举常量必须实现
    public abstract TrafficLight next();
    
    // 实例方法
    public void showStatus() {
        System.out.println(color + "灯: " + description);
    }
}

// 使用枚举
class TrafficLightDemo {
    public static void main(String[] args) {
        TrafficLight light = TrafficLight.RED;
        
        for (int i = 0; i < 5; i++) {
            light.showStatus();
            light = light.next();
        }
        
        // 作为接口类型使用
        Describable describable = TrafficLight.GREEN;
        System.out.println("描述: " + describable.getDescription());
    }
}

枚举中的抽象方法

public enum Calculator {
    ADD {
        @Override
        public double apply(double x, double y) {
            return x + y;
        }
        
        @Override
        public String getSymbol() {
            return "+";
        }
    },
    SUBTRACT {
        @Override
        public double apply(double x, double y) {
            return x - y;
        }
        
        @Override
        public String getSymbol() {
            return "-";
        }
    },
    MULTIPLY {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
        
        @Override
        public String getSymbol() {
            return "*";
        }
    },
    DIVIDE {
        @Override
        public double apply(double x, double y) {
            if (y == 0) throw new ArithmeticException("除数不能为零");
            return x / y;
        }
        
        @Override
        public String getSymbol() {
            return "/";
        }
    };
    
    // 抽象方法 - 每个枚举常量必须实现
    public abstract double apply(double x, double y);
    public abstract String getSymbol();
    
    // 通用方法
    public void calculateAndPrint(double x, double y) {
        try {
            double result = apply(x, y);
            System.out.printf("%.2f %s %.2f = %.2f%n", x, getSymbol(), y, result);
        } catch (ArithmeticException e) {
            System.out.println("计算错误: " + e.getMessage());
        }
    }
}

// 使用枚举
class CalculatorDemo {
    public static void main(String[] args) {
        Calculator.ADD.calculateAndPrint(10, 5);
        Calculator.DIVIDE.calculateAndPrint(10, 0); // 会捕获异常
    }
}

枚举的内置方法

public enum Status {
    PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED
}

class EnumMethodsDemo {
    public static void main(String[] args) {
        // values() - 获取所有枚举值
        Status[] allStatus = Status.values();
        System.out.println("所有状态:");
        for (Status status : allStatus) {
            System.out.println(status);
        }
        
        // valueOf() - 根据名称获取枚举实例
        Status status1 = Status.valueOf("COMPLETED");
        System.out.println("获取的状态: " + status1);
        
        // name() - 获取枚举常量的名称
        System.out.println("名称: " + status1.name());
        
        // ordinal() - 获取枚举常量的序号
        System.out.println("序号: " + status1.ordinal());
        
        // compareTo() - 比较枚举常量的顺序
        Status status2 = Status.PENDING;
        System.out.println("比较结果: " + status1.compareTo(status2));
        
        // toString() - 返回枚举常量的名称
        System.out.println("字符串表示: " + status1.toString());
        
        // getDeclaringClass() - 获取枚举类
        System.out.println("声明类: " + status1.getDeclaringClass());
    }
}

枚举在switch语句中的使用

public enum Command {
    START, STOP, PAUSE, RESUME, EXIT
}

class CommandProcessor {
    public void processCommand(Command command) {
        switch (command) {
            case START:
                System.out.println("启动系统...");
                break;
            case STOP:
                System.out.println("停止系统...");
                break;
            case PAUSE:
                System.out.println("暂停系统...");
                break;
            case RESUME:
                System.out.println("恢复系统...");
                break;
            case EXIT:
                System.out.println("退出系统...");
                System.exit(0);
                break;
            default:
                System.out.println("未知命令");
        }
    }
    
    // 使用增强的switch表达式(Java 14+)
    public String getCommandDescription(Command command) {
        return switch (command) {
            case START -> "启动操作";
            case STOP -> "停止操作";
            case PAUSE -> "暂停操作";
            case RESUME -> "恢复操作";
            case EXIT -> "退出操作";
            // 不需要default,因为枚举值已经全部覆盖
        };
    }
}

class SwitchDemo {
    public static void main(String[] args) {
        CommandProcessor processor = new CommandProcessor();
        
        processor.processCommand(Command.START);
        System.out.println(processor.getCommandDescription(Command.PAUSE));
    }
}

枚举集合类EnumSet和EnumMap

import java.util.EnumSet;
import java.util.EnumMap;

public enum UserRole {
    ADMIN, MODERATOR, USER, GUEST, DEVELOPER, TESTER
}

class EnumCollectionsDemo {
    public static void main(String[] args) {
        // EnumSet - 专门为枚举设计的高效Set实现
        EnumSet<UserRole> adminRoles = EnumSet.of(UserRole.ADMIN, UserRole.MODERATOR);
        EnumSet<UserRole> allRoles = EnumSet.allOf(UserRole.class);
        EnumSet<UserRole> developerRoles = EnumSet.range(UserRole.DEVELOPER, UserRole.TESTER);
        
        System.out.println("管理员角色: " + adminRoles);
        System.out.println("所有角色: " + allRoles);
        System.out.println("开发相关角色: " + developerRoles);
        
        // 判断包含
        System.out.println("包含ADMIN: " + adminRoles.contains(UserRole.ADMIN));
        System.out.println("包含GUEST: " + adminRoles.contains(UserRole.GUEST));
        
        // EnumMap - 专门为枚举设计的高效Map实现
        EnumMap<UserRole, String> roleDescriptions = new EnumMap<>(UserRole.class);
        roleDescriptions.put(UserRole.ADMIN, "系统管理员");
        roleDescriptions.put(UserRole.USER, "普通用户");
        roleDescriptions.put(UserRole.GUEST, "访客");
        
        System.out.println("角色描述:");
        for (UserRole role : roleDescriptions.keySet()) {
            System.out.println(role + ": " + roleDescriptions.get(role));
        }
        
        // 复杂的EnumSet操作
        EnumSet<UserRole> privilegedRoles = EnumSet.complementOf(
            EnumSet.of(UserRole.USER, UserRole.GUEST)
        );
        System.out.println("特权角色: " + privilegedRoles);
    }
}

枚举实现单例模式

// 使用枚举实现单例 - 线程安全,防止反射攻击
public enum Singleton {
    INSTANCE;
    
    // 成员变量
    private int value;
    private String data;
    
    // 构造方法
    Singleton() {
        this.value = 0;
        this.data = "默认数据";
        System.out.println("Singleton实例被创建");
    }
    
    // 业务方法
    public void doSomething() {
        System.out.println("单例方法执行, value: " + value);
    }
    
    public void increment() {
        value++;
    }
    
    // Getter和Setter
    public int getValue() {
        return value;
    }
    
    public void setValue(int value) {
        this.value = value;
    }
    
    public String getData() {
        return data;
    }
    
    public void setData(String data) {
        this.data = data;
    }
}

// 使用单例
class SingletonDemo {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        
        System.out.println("是否是同一个实例: " + (instance1 == instance2));
        
        instance1.doSomething();
        instance1.increment();
        instance2.doSomething(); // 可以看到value增加了
    }
}

枚举实现策略模式

public enum NotificationType {
    EMAIL {
        @Override
        public void sendNotification(String message, String recipient) {
            System.out.println("发送邮件到 " + recipient + ": " + message);
        }
        
        @Override
        public boolean validateRecipient(String recipient) {
            return recipient != null && recipient.contains("@");
        }
    },
    SMS {
        @Override
        public void sendNotification(String message, String recipient) {
            System.out.println("发送短信到 " + recipient + ": " + message);
        }
        
        @Override
        public boolean validateRecipient(String recipient) {
            return recipient != null && recipient.matches("\\d{11}");
        }
    },
    PUSH {
        @Override
        public void sendNotification(String message, String recipient) {
            System.out.println("发送推送通知到设备 " + recipient + ": " + message);
        }
        
        @Override
        public boolean validateRecipient(String recipient) {
            return recipient != null && recipient.startsWith("device_");
        }
    },
    SLACK {
        @Override
        public void sendNotification(String message, String recipient) {
            System.out.println("发送Slack消息到频道 " + recipient + ": " + message);
        }
        
        @Override
        public boolean validateRecipient(String recipient) {
            return recipient != null && recipient.startsWith("#");
        }
    };
    
    // 抽象方法
    public abstract void sendNotification(String message, String recipient);
    public abstract boolean validateRecipient(String recipient);
    
    // 默认方法
    public void sendSecureNotification(String message, String recipient) {
        if (validateRecipient(recipient)) {
            String encryptedMessage = encrypt(message);
            sendNotification(encryptedMessage, recipient);
        } else {
            System.out.println("无效的接收者: " + recipient);
        }
    }
    
    private String encrypt(String message) {
        // 简单的加密演示
        return "[加密]" + message + "[/加密]";
    }
    
    // 静态工具方法
    public static NotificationType fromString(String type) {
        try {
            return valueOf(type.toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("不支持的通知类型: " + type);
        }
    }
}

// 使用策略枚举
class NotificationService {
    public void sendNotification(NotificationType type, String message, String recipient) {
        type.sendSecureNotification(message, recipient);
    }
    
    public static void main(String[] args) {
        NotificationService service = new NotificationService();
        
        service.sendNotification(NotificationType.EMAIL, "Hello World", "test@example.com");
        service.sendNotification(NotificationType.SMS, "Hello World", "13800138000");
        service.sendNotification(NotificationType.PUSH, "Hello World", "device_12345");
        service.sendNotification(NotificationType.SLACK, "Hello World", "#general");
        
        // 测试无效的接收者
        service.sendNotification(NotificationType.EMAIL, "Test", "invalid-email");
    }
}

枚举实现状态机

public enum OrderStatus {
    // 订单状态流转
    CREATED {
        @Override
        public OrderStatus next() {
            return PAID;
        }
        
        @Override
        public boolean canCancel() {
            return true;
        }
    },
    PAID {
        @Override
        public OrderStatus next() {
            return SHIPPED;
        }
        
        @Override
        public boolean canCancel() {
            return true;
        }
    },
    SHIPPED {
        @Override
        public OrderStatus next() {
            return DELIVERED;
        }
        
        @Override
        public boolean canCancel() {
            return false;
        }
    },
    DELIVERED {
        @Override
        public OrderStatus next() {
            return COMPLETED;
        }
        
        @Override
        public boolean canCancel() {
            return false;
        }
    },
    COMPLETED {
        @Override
        public OrderStatus next() {
            return this; // 最终状态,不能再转换
        }
        
        @Override
        public boolean canCancel() {
            return false;
        }
    },
    CANCELLED {
        @Override
        public OrderStatus next() {
            return this; // 最终状态
        }
        
        @Override
        public boolean canCancel() {
            return false;
        }
    };
    
    // 抽象方法
    public abstract OrderStatus next();
    public abstract boolean canCancel();
    
    // 状态转换方法
    public OrderStatus transitionToNext() {
        if (this == COMPLETED || this == CANCELLED) {
            throw new IllegalStateException("状态 " + this + " 是最终状态,不能转换");
        }
        return next();
    }
    
    public OrderStatus cancel() {
        if (!canCancel()) {
            throw new IllegalStateException("状态 " + this + " 不能取消");
        }
        return CANCELLED;
    }
    
    // 判断方法
    public boolean isFinal() {
        return this == COMPLETED || this == CANCELLED;
    }
    
    public boolean isActive() {
        return !isFinal();
    }
}

// 订单类
class Order {
    private String orderId;
    private OrderStatus status;
    
    public Order(String orderId) {
        this.orderId = orderId;
        this.status = OrderStatus.CREATED;
    }
    
    public void proceedToNext() {
        try {
            this.status = status.transitionToNext();
            System.out.println("订单 " + orderId + " 状态变为: " + status);
        } catch (IllegalStateException e) {
            System.out.println("状态转换失败: " + e.getMessage());
        }
    }
    
    public void cancel() {
        try {
            this.status = status.cancel();
            System.out.println("订单 " + orderId + " 已取消");
        } catch (IllegalStateException e) {
            System.out.println("取消失败: " + e.getMessage());
        }
    }
    
    // Getter
    public OrderStatus getStatus() {
        return status;
    }
}

class StateMachineDemo {
    public static void main(String[] args) {
        Order order = new Order("ORDER_001");
        
        // 正常流程
        order.proceedToNext(); // CREATED -> PAID
        order.proceedToNext(); // PAID -> SHIPPED
        
        // 尝试取消(应该失败)
        order.cancel();
        
        order.proceedToNext(); // SHIPPED -> DELIVERED
        order.proceedToNext(); // DELIVERED -> COMPLETED
        
        // 尝试继续转换(应该失败)
        order.proceedToNext();
    }
}

复杂示例:权限系统设计

import java.util.EnumSet;
import java.util.Set;

public enum Permission {
    // 权限定义
    READ(1, "读取权限"),
    WRITE(2, "写入权限"),
    EXECUTE(4, "执行权限"),
    DELETE(8, "删除权限"),
    CREATE(16, "创建权限"),
    ADMIN(32, "管理员权限"),
    AUDIT(64, "审计权限"),
    BACKUP(128, "备份权限");
    
    private final int value;
    private final String description;
    
    Permission(int value, String description) {
        this.value = value;
        this.description = description;
    }
    
    public int getValue() {
        return value;
    }
    
    public String getDescription() {
        return description;
    }
    
    // 权限组合操作
    public static Set<Permission> fromInt(int permissionValue) {
        Set<Permission> permissions = EnumSet.noneOf(Permission.class);
        for (Permission permission : values()) {
            if ((permissionValue & permission.value) != 0) {
                permissions.add(permission);
            }
        }
        return permissions;
    }
    
    public static int toInt(Set<Permission> permissions) {
        int value = 0;
        for (Permission permission : permissions) {
            value |= permission.value;
        }
        return value;
    }
    
    public static boolean hasPermission(int permissionValue, Permission required) {
        return (permissionValue & required.value) != 0;
    }
    
    public static int addPermission(int permissionValue, Permission permission) {
        return permissionValue | permission.value;
    }
    
    public static int removePermission(int permissionValue, Permission permission) {
        return permissionValue & ~permission.value;
    }
    
    // 预定义的权限组合
    public static final int BASIC_ACCESS = toInt(EnumSet.of(READ, WRITE));
    public static final int FULL_ACCESS = toInt(EnumSet.of(READ, WRITE, EXECUTE, DELETE, CREATE));
    public static final int ADMIN_ACCESS = toInt(EnumSet.allOf(Permission.class));
}

// 用户权限管理
class User {
    private String username;
    private int permissions;
    
    public User(String username, int permissions) {
        this.username = username;
        this.permissions = permissions;
    }
    
    public boolean hasPermission(Permission permission) {
        return Permission.hasPermission(permissions, permission);
    }
    
    public void grantPermission(Permission permission) {
        permissions = Permission.addPermission(permissions, permission);
        System.out.println("授予 " + username + " 权限: " + permission.getDescription());
    }
    
    public void revokePermission(Permission permission) {
        permissions = Permission.removePermission(permissions, permission);
        System.out.println("撤销 " + username + " 权限: " + permission.getDescription());
    }
    
    public void printPermissions() {
        Set<Permission> userPermissions = Permission.fromInt(permissions);
        System.out.println(username + " 的权限:");
        for (Permission perm : userPermissions) {
            System.out.println("  - " + perm.getDescription());
        }
    }
}

class PermissionSystemDemo {
    public static void main(String[] args) {
        // 创建用户
        User user = new User("张三", Permission.BASIC_ACCESS);
        user.printPermissions();
        
        // 授予额外权限
        user.grantPermission(Permission.DELETE);
        user.grantPermission(Permission.EXECUTE);
        user.printPermissions();
        
        // 检查权限
        System.out.println("是否有读取权限: " + user.hasPermission(Permission.READ));
        System.out.println("是否有管理员权限: " + user.hasPermission(Permission.ADMIN));
        
        // 撤销权限
        user.revokePermission(Permission.DELETE);
        user.printPermissions();
        
        // 使用预定义权限组合
        User admin = new User("管理员", Permission.ADMIN_ACCESS);
        admin.printPermissions();
    }
}

设计原则

// 1. 使用枚举代替常量
public class GoodDesign {
    // 好的设计:使用枚举
    public enum LogLevel {
        DEBUG, INFO, WARN, ERROR
    }
    
    public void log(LogLevel level, String message) {
        // 实现日志记录
    }
}

// 2. 枚举应该是不可变的
public enum ImmutableEnum {
    VALUE1("data1"),
    VALUE2("data2");
    
    private final String data; // 使用final确保不可变
    
    ImmutableEnum(String data) {
        this.data = data;
    }
    
    public String getData() {
        return data;
    }
}

// 3. 合理使用枚举方法
public enum SmartEnum {
    FIRST,
    SECOND,
    THIRD;
    
    // 提供有用的方法
    public boolean isFirst() {
        return this == FIRST;
    }
    
    public boolean isLast() {
        return this == THIRD;
    }
    
    public SmartEnum getNext() {
        if (this == THIRD) return FIRST;
        return values()[ordinal() + 1];
    }
}

// 4. 避免在枚举中保存大量数据
public enum LightweightEnum {
    OPTION_A,
    OPTION_B,
    OPTION_C;
    
    // 避免这样设计
    // private byte[] largeData = new byte[1024 * 1024]; // 1MB数据
}

总结

Java枚举的核心要点:

  1. 定义:使用enum关键字,隐含继承java.lang.Enum
  2. 常量:枚举常量是类的实例,在类加载时创建
  3. 构造方法:必须是private,在常量声明时调用
  4. 方法:可以有实例方法、静态方法、抽象方法
  5. 接口:枚举可以实现接口
  6. 内置方法values(), valueOf(), name(), ordinal()
  7. 集合支持EnumSetEnumMap提供高性能操作
  8. 设计模式:完美实现单例模式、策略模式、状态机等
  9. 线程安全:枚举实例创建是线程安全的

注解 (Annotation)

注解的定义和基本概念

注解定义语法

[访问修饰符] @interface 注解名 {
    // 注解元素(方法)
    // 默认值
}

基本注解示例

// 最简单的注解
public @interface MyAnnotation {
}

// 使用注解
@MyAnnotation
class MyClass {
    @MyAnnotation
    public void myMethod() {
    }
}

注解元素(方法)

import java.lang.annotation.*;

// 定义包含各种类型元素的注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface ComplexAnnotation {
    // 基本类型
    int id() default 0;
    String name() default "";
    double version() default 1.0;
    boolean enabled() default true;
    
    // 数组类型
    String[] tags() default {};
    int[] values() default {};
    
    // 枚举类型
    Status status() default Status.ACTIVE;
    
    // Class类型
    Class<?> processor() default Void.class;
    
    // 注解类型
    SubAnnotation subAnnotation() default @SubAnnotation;
    
    // 特殊值 - 不需要默认值
    String value() default "";
}

// 嵌套的注解
@interface SubAnnotation {
    String info() default "sub";
}

// 枚举用于注解
enum Status {
    ACTIVE, INACTIVE, PENDING
}

// 使用复杂注解
@ComplexAnnotation(
    id = 1,
    name = "测试类",
    version = 2.0,
    tags = {"java", "annotation"},
    values = {1, 2, 3},
    status = Status.ACTIVE,
    processor = String.class,
    subAnnotation = @SubAnnotation(info = "自定义信息"),
    value = "主要值"
)
class AnnotatedClass {
    @ComplexAnnotation(name = "字段注解", enabled = false)
    private String data;
    
    @ComplexAnnotation(id = 100, value = "方法注解")
    public void process() {
    }
}

元注解(Meta-Annotations)

import java.lang.annotation.*;

// @Target - 指定注解可以应用的位置
@Target({
    ElementType.TYPE,           // 类、接口、枚举
    ElementType.FIELD,          // 字段
    ElementType.METHOD,         // 方法
    ElementType.PARAMETER,      // 参数
    ElementType.CONSTRUCTOR,    // 构造方法
    ElementType.LOCAL_VARIABLE, // 局部变量
    ElementType.ANNOTATION_TYPE,// 注解
    ElementType.PACKAGE,        // 包
    ElementType.TYPE_PARAMETER, // 类型参数(Java 8+)
    ElementType.TYPE_USE        // 类型使用(Java 8+)
})
// @Retention - 指定注解保留策略
@Retention(RetentionPolicy.RUNTIME) // 运行时保留
// @Retention(RetentionPolicy.SOURCE)  // 仅源码阶段
// @Retention(RetentionPolicy.CLASS)   // 编译阶段

// @Documented - 包含在Javadoc中
@Documented

// @Inherited - 允许子类继承
@Inherited

// @Repeatable - 可重复注解(Java 8+)
@Repeatable(Roles.class)
public @interface Role {
    String value();
}

// 容器注解
@interface Roles {
    Role[] value();
}

// 使用示例
@Role("管理员")
@Role("开发者")  // 可重复注解
class User {
}

内置的标准注解

import java.util.*;

// 使用内置注解的示例
@SuppressWarnings({"unchecked", "deprecation"})
public class BuiltInAnnotations {
    
    // @Override - 表示方法重写
    @Override
    public String toString() {
        return "BuiltInAnnotations实例";
    }
    
    // @Deprecated - 标记已过时
    @Deprecated(since = "2.0", forRemoval = true)
    public void oldMethod() {
        System.out.println("这是过时的方法");
    }
    
    // @SuppressWarnings - 抑制警告
    @SuppressWarnings("rawtypes")
    public void processList(List list) {
        // 不使用泛型的代码
    }
    
    // @SafeVarargs - 表示方法不会对可变参数进行危险操作
    @SafeVarargs
    public final <T> void safeMethod(T... args) {
        for (T arg : args) {
            System.out.println(arg);
        }
    }
    
    // @FunctionalInterface - 函数式接口
    @FunctionalInterface
    interface MyFunction {
        void apply(String input);
        // 只能有一个抽象方法
        // void anotherMethod(); // 编译错误
    }
    
    public void useNewMethod() {
        System.out.println("使用新方法");
    }
    
    public static void main(String[] args) {
        BuiltInAnnotations example = new BuiltInAnnotations();
        example.oldMethod(); // 编译器会显示过时警告
    }
}

注解的三种保留策略

// SOURCE级别注解 - 仅在源码中保留
@Retention(RetentionPolicy.SOURCE)
@interface SourceAnnotation {
    String value();
}

// CLASS级别注解 - 编译到class文件,但运行时不可见
@Retention(RetentionPolicy.CLASS)
@interface ClassAnnotation {
    String value();
}

// RUNTIME级别注解 - 运行时可通过反射获取
@Retention(RetentionPolicy.RUNTIME)
@interface RuntimeAnnotation {
    String value();
}

// 使用不同保留策略的注解
@SourceAnnotation("源码注解")
@ClassAnnotation("类文件注解")
@RuntimeAnnotation("运行时注解")
public class RetentionExample {
    @SourceAnnotation("方法源码注解")
    public void method() {
    }
}

运行时注解处理(反射)

import java.lang.reflect.*;

// 自定义运行时注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@interface MyRuntimeAnnotation {
    String name() default "";
    int priority() default 0;
    String[] tags() default {};
}

// 使用注解的类
@MyRuntimeAnnotation(name = "用户服务", priority = 1, tags = {"service", "user"})
class UserService {
    @MyRuntimeAnnotation(name = "用户ID")
    private Long userId;
    
    @MyRuntimeAnnotation(name = "获取用户", priority = 2)
    public void getUser() {
        System.out.println("获取用户信息");
    }
    
    @MyRuntimeAnnotation
    public void defaultMethod() {
    }
}

// 注解处理器
class AnnotationProcessor {
    public static void processAnnotations(Class<?> clazz) {
        System.out.println("处理类: " + clazz.getName());
        
        // 处理类级别的注解
        if (clazz.isAnnotationPresent(MyRuntimeAnnotation.class)) {
            MyRuntimeAnnotation annotation = clazz.getAnnotation(MyRuntimeAnnotation.class);
            System.out.println("类注解 - 名称: " + annotation.name() + 
                             ", 优先级: " + annotation.priority() +
                             ", 标签: " + String.join(", ", annotation.tags()));
        }
        
        // 处理字段级别的注解
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(MyRuntimeAnnotation.class)) {
                MyRuntimeAnnotation annotation = field.getAnnotation(MyRuntimeAnnotation.class);
                System.out.println("字段注解 - 字段: " + field.getName() + 
                                 ", 名称: " + annotation.name());
            }
        }
        
        // 处理方法级别的注解
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(MyRuntimeAnnotation.class)) {
                MyRuntimeAnnotation annotation = method.getAnnotation(MyRuntimeAnnotation.class);
                System.out.println("方法注解 - 方法: " + method.getName() + 
                                 ", 名称: " + annotation.name() +
                                 ", 优先级: " + annotation.priority());
            }
        }
    }
    
    public static void main(String[] args) {
        processAnnotations(UserService.class);
    }
}

编译时注解处理器(自定义注解处理器)

import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.*;
import java.util.*;
import java.io.*;

// 编译时注解
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@interface GenerateBuilder {
    String className() default "";
}

// 使用注解
@GenerateBuilder(className = "UserBuilder")
class User {
    private String name;
    private int age;
    
    // getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

// 注解处理器(需要配置到META-INF/services/javax.annotation.processing.Processor)
@SupportedAnnotationTypes("GenerateBuilder")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class BuilderProcessor extends AbstractProcessor {
    
    @Override
    public boolean process(Set<? extends TypeElement> annotations, 
                          RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> annotatedElements = 
                roundEnv.getElementsAnnotatedWith(annotation);
            
            for (Element element : annotatedElements) {
                if (element.getKind() == ElementKind.CLASS) {
                    generateBuilder((TypeElement) element);
                }
            }
        }
        return true;
    }
    
    private void generateBuilder(TypeElement classElement) {
        GenerateBuilder annotation = classElement.getAnnotation(GenerateBuilder.class);
        String className = annotation.className();
        String originalClassName = classElement.getSimpleName().toString();
        
        if (className.isEmpty()) {
            className = originalClassName + "Builder";
        }
        
        StringBuilder builder = new StringBuilder();
        builder.append("public class ").append(className).append(" {\n");
        builder.append("    private ").append(originalClassName).append(" instance = new ").append(originalClassName).append("();\n\n");
        
        // 为每个字段生成setter方法
        for (Element enclosed : classElement.getEnclosedElements()) {
            if (enclosed.getKind() == ElementKind.FIELD) {
                String fieldName = enclosed.getSimpleName().toString();
                String fieldType = enclosed.asType().toString();
                
                builder.append("    public ").append(className).append(" set").append(capitalize(fieldName))
                      .append("(").append(fieldType).append(" ").append(fieldName).append(") {\n")
                      .append("        instance.set").append(capitalize(fieldName)).append("(").append(fieldName).append(");\n")
                      .append("        return this;\n")
                      .append("    }\n\n");
            }
        }
        
        builder.append("    public ").append(originalClassName).append(" build() {\n")
              .append("        return instance;\n")
              .append("    }\n")
              .append("}\n");
        
        // 写入文件
        try {
            JavaFileObject builderFile = processingEnv.getFiler()
                .createSourceFile(className);
            try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
                out.println(builder.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private String capitalize(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
}

自定义验证注解(参数验证注解)

import javax.validation.*;
import java.lang.annotation.*;
import java.util.regex.Pattern;

// 自定义验证注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EmailValidator.class)
@interface ValidEmail {
    String message() default "无效的邮箱地址";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

// 验证器实现
class EmailValidator implements ConstraintValidator<ValidEmail, String> {
    private static final String EMAIL_PATTERN = 
        "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
    
    @Override
    public void initialize(ValidEmail constraintAnnotation) {
    }
    
    @Override
    public boolean isValid(String email, ConstraintValidatorContext context) {
        if (email == null) {
            return false;
        }
        return Pattern.matches(EMAIL_PATTERN, email);
    }
}

// 范围验证注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RangeValidator.class)
@interface ValidRange {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "数值超出范围";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

class RangeValidator implements ConstraintValidator<ValidRange, Integer> {
    private int min;
    private int max;
    
    @Override
    public void initialize(ValidRange constraintAnnotation) {
        this.min = constraintAnnotation.min();
        this.max = constraintAnnotation.max();
    }
    
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value == null) {
            return false;
        }
        return value >= min && value <= max;
    }
}

// 使用验证注解的类
class User {
    @ValidEmail
    private String email;
    
    @ValidRange(min = 1, max = 120)
    private Integer age;
    
    // 构造方法、getter、setter
    public User(String email, Integer age) {
        this.email = email;
        this.age = age;
    }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

// 验证工具类
class ValidationUtil {
    public static void validate(Object obj) {
        // 简化版的验证逻辑
        // 实际中可以使用Hibernate Validator等框架
        System.out.println("验证对象: " + obj.getClass().getSimpleName());
    }
    
    public static void main(String[] args) {
        User user1 = new User("valid@example.com", 25);
        User user2 = new User("invalid-email", 150);
        
        validate(user1);
        validate(user2);
    }
}

Spring风格的注解(模仿Spring框架的注解)

import java.lang.annotation.*;

// 组件注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
@interface Service {
    String value() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
@interface Repository {
    String value() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
@interface Controller {
    String value() default "";
}

// 元注解
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Component {
    String value() default "";
}

// 自动注入注解
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Autowired {
    boolean required() default true;
}

// 配置注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Configuration {
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Bean {
    String name() default "";
    boolean autowire() default true;
}

// 请求映射注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface RequestMapping {
    String value() default "";
    RequestMethod method() default RequestMethod.GET;
}

enum RequestMethod {
    GET, POST, PUT, DELETE, PATCH
}

// 使用Spring风格注解的示例
@Configuration
class AppConfig {
    @Bean(name = "userService")
    public UserService userService() {
        return new UserService();
    }
}

@Service("userService")
class UserService {
    public String getUserInfo() {
        return "用户信息";
    }
}

@Controller
@RequestMapping("/user")
class UserController {
    @Autowired
    private UserService userService;
    
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public String getUserInfo() {
        return userService.getUserInfo();
    }
}

@Repository
class UserRepository {
    public String findUser() {
        return "从数据库查询用户";
    }
}

测试框架注解(模仿JUnit的测试注解)

import java.lang.annotation.*;
import java.lang.reflect.*;

// 测试框架注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test {
    Class<? extends Throwable> expected() default None.class;
    long timeout() default 0L;
    
    class None extends Throwable {
        private None() {}
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Before {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface After {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface BeforeClass {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface AfterClass {
}

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Ignore {
    String value() default "";
}

// 简单的测试运行器
class SimpleTestRunner {
    public static void runTests(Class<?> testClass) throws Exception {
        System.out.println("运行测试类: " + testClass.getSimpleName());
        
        Object testInstance = testClass.getDeclaredConstructor().newInstance();
        
        // 执行 @BeforeClass 方法
        for (Method method : testClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(BeforeClass.class)) {
                method.invoke(null);
            }
        }
        
        // 执行测试方法
        for (Method method : testClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(Test.class)) {
                if (method.isAnnotationPresent(Ignore.class)) {
                    Ignore ignore = method.getAnnotation(Ignore.class);
                    System.out.println("忽略测试: " + method.getName() + " - " + ignore.value());
                    continue;
                }
                
                Test testAnnotation = method.getAnnotation(Test.class);
                
                // 执行 @Before 方法
                for (Method beforeMethod : testClass.getDeclaredMethods()) {
                    if (beforeMethod.isAnnotationPresent(Before.class)) {
                        beforeMethod.invoke(testInstance);
                    }
                }
                
                System.out.print("执行测试: " + method.getName());
                
                long startTime = System.currentTimeMillis();
                try {
                    method.invoke(testInstance);
                    
                    // 检查是否期望异常
                    if (testAnnotation.expected() != Test.None.class) {
                        System.out.println(" - 失败: 期望异常 " + testAnnotation.expected().getSimpleName());
                    } else {
                        System.out.println(" - 通过");
                    }
                } catch (InvocationTargetException e) {
                    Throwable cause = e.getCause();
                    if (testAnnotation.expected().isInstance(cause)) {
                        System.out.println(" - 通过 (抛出预期异常)");
                    } else {
                        System.out.println(" - 失败: " + cause.getMessage());
                    }
                }
                
                // 检查超时
                long duration = System.currentTimeMillis() - startTime;
                if (testAnnotation.timeout() > 0 && duration > testAnnotation.timeout()) {
                    System.out.println(" - 失败: 超时 " + duration + "ms");
                }
                
                // 执行 @After 方法
                for (Method afterMethod : testClass.getDeclaredMethods()) {
                    if (afterMethod.isAnnotationPresent(After.class)) {
                        afterMethod.invoke(testInstance);
                    }
                }
            }
        }
        
        // 执行 @AfterClass 方法
        for (Method method : testClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(AfterClass.class)) {
                method.invoke(null);
            }
        }
    }
}

// 测试类示例
class CalculatorTest {
    private Calculator calculator;
    
    @BeforeClass
    public static void setUpClass() {
        System.out.println("测试类初始化");
    }
    
    @Before
    public void setUp() {
        calculator = new Calculator();
        System.out.println("测试前准备");
    }
    
    @Test
    public void testAddition() {
        int result = calculator.add(2, 3);
        assert result == 5 : "加法测试失败";
    }
    
    @Test(expected = ArithmeticException.class)
    public void testDivisionByZero() {
        calculator.divide(10, 0);
    }
    
    @Test(timeout = 1000L)
    public void testTimeout() {
        // 模拟耗时操作
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    @Ignore("暂时跳过")
    @Test
    public void testIgnored() {
        System.out.println("这个测试被跳过了");
    }
    
    @After
    public void tearDown() {
        calculator = null;
        System.out.println("测试后清理");
    }
    
    @AfterClass
    public static void tearDownClass() {
        System.out.println("测试类清理");
    }
}

class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    
    public int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("除数不能为零");
        }
        return a / b;
    }
}

复杂示例:模仿Hibernate的ORM注解

import java.lang.annotation.*;
import java.util.*;

// ORM注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Entity
@interface Table {
    String name() default "";
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Column {
    String name() default "";
    boolean nullable() default true;
    int length() default 255;
    boolean unique() default false;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Id {
    String generator() default "auto";
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface GeneratedValue {
    GenerationType strategy() default GenerationType.AUTO;
}

enum GenerationType {
    AUTO, IDENTITY, SEQUENCE, TABLE
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface OneToMany {
    String mappedBy() default "";
    CascadeType[] cascade() default {};
    FetchType fetch() default FetchType.LAZY;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ManyToOne {
    CascadeType[] cascade() default {};
    FetchType fetch() default FetchType.EAGER;
    boolean optional() default true;
}

enum CascadeType {
    ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH
}

enum FetchType {
    LAZY, EAGER
}

@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Entity {
}

// 使用ORM注解的实体类
@Table(name = "users")
class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username", nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(name = "email", nullable = false)
    private String email;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Order> orders = new ArrayList<>();
    
    // 构造方法、getter、setter
    public User() {}
    
    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }
    
    // getter和setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public List<Order> getOrders() { return orders; }
    public void setOrders(List<Order> orders) { this.orders = orders; }
}

@Table(name = "orders")
class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "order_number", nullable = false, unique = true)
    private String orderNumber;
    
    @Column(name = "total_amount")
    private Double totalAmount;
    
    @ManyToOne(fetch = FetchType.EAGER)
    private User user;
    
    // 构造方法、getter、setter
    public Order() {}
    
    public Order(String orderNumber, Double totalAmount, User user) {
        this.orderNumber = orderNumber;
        this.totalAmount = totalAmount;
        this.user = user;
    }
    
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getOrderNumber() { return orderNumber; }
    public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; }
    public Double getTotalAmount() { return totalAmount; }
    public void setTotalAmount(Double totalAmount) { this.totalAmount = totalAmount; }
    public User getUser() { return user; }
    public void setUser(User user) { this.user = user; }
}

// 简单的ORM处理器
class SimpleORM {
    public static String generateCreateTableSQL(Class<?> entityClass) {
        if (!entityClass.isAnnotationPresent(Table.class)) {
            throw new IllegalArgumentException("类 " + entityClass.getName() + " 不是实体类");
        }
        
        Table table = entityClass.getAnnotation(Table.class);
        String tableName = table.name().isEmpty() ? 
            entityClass.getSimpleName().toLowerCase() : table.name();
        
        StringBuilder sql = new StringBuilder();
        sql.append("CREATE TABLE ").append(tableName).append(" (\n");
        
        List<String> columns = new ArrayList<>();
        List<String> constraints = new ArrayList<>();
        
        for (java.lang.reflect.Field field : entityClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Column.class)) {
                Column column = field.getAnnotation(Column.class);
                String columnName = column.name().isEmpty() ? 
                    field.getName() : column.name();
                
                String columnType = getSQLType(field.getType());
                StringBuilder columnDef = new StringBuilder();
                columnDef.append("    ").append(columnName).append(" ").append(columnType);
                
                if (!column.nullable()) {
                    columnDef.append(" NOT NULL");
                }
                
                if (column.unique()) {
                    constraints.add("    UNIQUE (" + columnName + ")");
                }
                
                if (field.isAnnotationPresent(Id.class)) {
                    columnDef.append(" PRIMARY KEY");
                }
                
                columns.add(columnDef.toString());
            }
        }
        
        sql.append(String.join(",\n", columns));
        
        if (!constraints.isEmpty()) {
            sql.append(",\n").append(String.join(",\n", constraints));
        }
        
        sql.append("\n);");
        return sql.toString();
    }
    
    private static String getSQLType(Class<?> type) {
        if (type == Long.class || type == long.class) return "BIGINT";
        if (type == Integer.class || type == int.class) return "INT";
        if (type == String.class) return "VARCHAR(255)";
        if (type == Double.class || type == double.class) return "DECIMAL(10,2)";
        if (type == Boolean.class || type == boolean.class) return "BOOLEAN";
        if (type == Date.class) return "DATETIME";
        return "TEXT";
    }
    
    public static void main(String[] args) {
        System.out.println("User表SQL:");
        System.out.println(generateCreateTableSQL(User.class));
        
        System.out.println("\nOrder表SQL:");
        System.out.println(generateCreateTableSQL(Order.class));
    }
}

设计原则

// 1. 注解应该简单明了
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface SimpleAnnotation {
    String value(); // 使用value作为主要元素
}

// 2. 提供合理的默认值
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface GoodDesign {
    String name() default "";
    int retries() default 3;
    boolean async() default false;
}

// 3. 使用枚举提高类型安全
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface StatusField {
    Status status() default Status.ACTIVE;
}

enum Status {
    ACTIVE, INACTIVE, PENDING, DELETED
}

// 4. 避免注解过度复杂
// 不好的设计:注解包含太多复杂逻辑
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface OverComplex {
    Class<?>[] types();
    String[] names();
    int[] values();
    boolean[] flags();
}

// 好的设计:拆分多个简单注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Cache {
    String key();
    long ttl() default 3600;
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Retry {
    int attempts() default 3;
    long delay() default 1000;
}

// 5. 文档化注解的使用
/**
 * 用于标记需要权限验证的方法
 * 
 * 示例:
 * {@code
 * @RequiresPermission("user:read")
 * public void getUser() { ... }
 * }
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface RequiresPermission {
    String value();
    String description() default "";
}

总结

Java注解的核心要点:

  1. 定义:使用@interface关键字,本质是接口
  2. 元素:可以定义各种类型的元素(方法),支持默认值
  3. 元注解@Target, @Retention, @Documented, @Inherited, @Repeatable
  4. 保留策略SOURCE, CLASS, RUNTIME
  5. 处理方式:编译时处理(注解处理器)或运行时处理(反射)
  6. 内置注解@Override, @Deprecated, @SuppressWarnings, @SafeVarargs, @FunctionalInterface
  7. 应用场景:配置、验证、代码生成、框架集成等

记录 (Record)

记录类的定义和基本概念

记录类定义语法

[访问修饰符] record 记录名(参数列表) [implements 接口1, 接口2, ...] {
    // 紧凑构造方法
    // 实例方法
    // 静态方法
    // 静态字段
    // 嵌套类型
}

基本记录类示例

// 最简单的记录类
public record Point(int x, int y) {
}

// 使用记录类
class RecordDemo {
    public static void main(String[] args) {
        Point p1 = new Point(10, 20);
        Point p2 = new Point(10, 20);
        
        System.out.println(p1);         // 自动生成toString: Point[x=10, y=20]
        System.out.println(p1.x());     // 自动生成的访问器方法
        System.out.println(p1.y());
        System.out.println(p1.equals(p2)); // 自动生成equals: true
        System.out.println(p1.hashCode() == p2.hashCode()); // 自动生成hashCode: true
    }
}

记录类的组件(自动生成的成员)

// 记录类自动生成以下成员:
public record Person(String name, int age, String email) {
    // 自动生成:
    // 1. private final 字段:name, age, email
    // 2. 规范构造方法:Person(String name, int age, String email)
    // 3. 访问器方法:name(), age(), email()
    // 4. equals() 方法
    // 5. hashCode() 方法
    // 6. toString() 方法
}

// 手动实现等效的普通类
class TraditionalPerson {
    private final String name;
    private final int age;
    private final String email;
    
    public TraditionalPerson(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
    
    public String name() { return name; }
    public int age() { return age; }
    public String email() { return email; }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof TraditionalPerson)) return false;
        TraditionalPerson that = (TraditionalPerson) o;
        return age == that.age && 
               Objects.equals(name, that.name) && 
               Objects.equals(email, that.email);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age, email);
    }
    
    @Override
    public String toString() {
        return "TraditionalPerson[name=" + name + ", age=" + age + ", email=" + email + "]";
    }
}

记录类的构造方法

紧凑构造方法

public record User(String username, String email, int age) {
    // 紧凑构造方法 - 用于参数验证和规范化
    public User {
        // 参数验证
        if (username == null || username.trim().isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("年龄必须在0-150之间");
        }
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
        
        // 规范化
        username = username.trim();
        email = email.toLowerCase();
        
        // 不需要显式赋值,编译器会自动处理
    }
}

// 使用验证
class ConstructorDemo {
    public static void main(String[] args) {
        try {
            User user1 = new User("  John  ", "JOHN@EXAMPLE.COM", 25);
            System.out.println(user1); // User[username=John, email=john@example.com, age=25]
            
            User user2 = new User("", "invalid", 200); // 抛出异常
        } catch (IllegalArgumentException e) {
            System.out.println("创建用户失败: " + e.getMessage());
        }
    }
}

自定义构造方法

public record Employee(String id, String name, String department, double salary) {
    // 自定义构造方法 - 必须调用主构造方法
    public Employee(String name, String department) {
        this(generateId(), name, department, 0.0);
    }
    
    public Employee(String name) {
        this(generateId(), name, "未分配", 0.0);
    }
    
    // 静态方法生成ID
    private static String generateId() {
        return "EMP_" + System.currentTimeMillis() + "_" + 
               (int)(Math.random() * 1000);
    }
    
    // 工厂方法
    public static Employee createManager(String name) {
        return new Employee(generateId(), name, "管理部", 10000.0);
    }
    
    // 紧凑构造方法
    public Employee {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("员工姓名不能为空");
        }
        if (salary < 0) {
            throw new IllegalArgumentException("薪资不能为负数");
        }
        name = name.trim();
    }
}

class CustomConstructorDemo {
    public static void main(String[] args) {
        Employee emp1 = new Employee("E001", "张三", "技术部", 8000.0);
        Employee emp2 = new Employee("李四", "市场部"); // 使用自定义构造方法
        Employee emp3 = new Employee("王五"); // 使用另一个自定义构造方法
        Employee manager = Employee.createManager("赵六"); // 工厂方法
        
        System.out.println(emp1);
        System.out.println(emp2);
        System.out.println(emp3);
        System.out.println(manager);
    }
}

记录类的实例方法和静态方法

import java.time.LocalDate;
import java.time.Period;

public record Person(String name, LocalDate birthDate, String email) {
    // 实例方法
    public int getAge() {
        return Period.between(birthDate, LocalDate.now()).getYears();
    }
    
    public boolean isAdult() {
        return getAge() >= 18;
    }
    
    public String getInitials() {
        String[] names = name.split(" ");
        if (names.length == 1) {
            return name.substring(0, 1).toUpperCase();
        }
        return (names[0].substring(0, 1) + names[names.length - 1].substring(0, 1)).toUpperCase();
    }
    
    // 静态方法
    public static Person create(String name, int birthYear, int birthMonth, int birthDay, String email) {
        LocalDate birthDate = LocalDate.of(birthYear, birthMonth, birthDay);
        return new Person(name, birthDate, email);
    }
    
    public static boolean isValidEmail(String email) {
        return email != null && email.contains("@") && email.contains(".");
    }
    
    // 重写访问器方法
    @Override
    public String name() {
        // 返回格式化的姓名
        return name.toUpperCase();
    }
    
    // 紧凑构造方法
    public Person {
        if (birthDate != null && birthDate.isAfter(LocalDate.now())) {
            throw new IllegalArgumentException("出生日期不能在未来");
        }
        if (!isValidEmail(email)) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
    }
}

class MethodDemo {
    public static void main(String[] args) {
        Person person = Person.create("张三", 1990, 5, 15, "zhangsan@example.com");
        
        System.out.println("姓名: " + person.name());
        System.out.println("年龄: " + person.getAge());
        System.out.println("是否成年: " + person.isAdult());
        System.out.println("姓名缩写: " + person.getInitials());
        System.out.println("完整信息: " + person);
    }
}

记录类的静态字段(静态字段和常量)

public record BankAccount(String accountNumber, String accountHolder, double balance) {
    // 静态字段
    private static final String BANK_NAME = "Java银行";
    private static final double MIN_BALANCE = 0.0;
    private static final double MAX_BALANCE = 1_000_000.0;
    private static int accountCount = 0;
    
    // 静态初始化块
    static {
        System.out.println("银行账户系统初始化");
    }
    
    // 紧凑构造方法
    public BankAccount {
        if (balance < MIN_BALANCE) {
            throw new IllegalArgumentException("余额不能为负数");
        }
        if (balance > MAX_BALANCE) {
            throw new IllegalArgumentException("余额超过上限");
        }
        if (accountNumber == null || accountNumber.length() != 16) {
            throw new IllegalArgumentException("账号必须是16位");
        }
        
        accountCount++;
    }
    
    // 实例方法
    public BankAccount deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("存款金额必须为正数");
        }
        return new BankAccount(accountNumber, accountHolder, balance + amount);
    }
    
    public BankAccount withdraw(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("取款金额必须为正数");
        }
        if (balance - amount < MIN_BALANCE) {
            throw new IllegalArgumentException("余额不足");
        }
        return new BankAccount(accountNumber, accountHolder, balance - amount);
    }
    
    // 静态方法
    public static String getBankName() {
        return BANK_NAME;
    }
    
    public static int getAccountCount() {
        return accountCount;
    }
    
    public static BankAccount createAccount(String accountHolder, double initialBalance) {
        String accountNumber = generateAccountNumber();
        return new BankAccount(accountNumber, accountHolder, initialBalance);
    }
    
    private static String generateAccountNumber() {
        return "62" + System.currentTimeMillis() % 10_000_000_000L;
    }
    
    // 重写toString以包含静态信息
    @Override
    public String toString() {
        return String.format("BankAccount[银行=%s, 账号=%s, 户主=%s, 余额=%.2f]",
                BANK_NAME, accountNumber, accountHolder, balance);
    }
}

class StaticFieldDemo {
    public static void main(String[] args) {
        System.out.println("银行名称: " + BankAccount.getBankName());
        
        BankAccount account1 = BankAccount.createAccount("张三", 1000.0);
        BankAccount account2 = BankAccount.createAccount("李四", 500.0);
        
        System.out.println(account1);
        System.out.println(account2);
        
        // 存款取款操作(返回新对象)
        BankAccount updatedAccount = account1.deposit(500.0).withdraw(200.0);
        System.out.println("更新后: " + updatedAccount);
        
        System.out.println("总账户数: " + BankAccount.getAccountCount());
    }
}

记录类实现接口

// 定义接口
interface Identifiable {
    String getId();
    boolean isValid();
}

interface Auditable {
    void audit();
    default String getAuditInfo() {
        return "审计信息";
    }
}

interface JsonSerializable {
    String toJson();
}

// 记录类实现多个接口
public record Product(String id, String name, double price, int stock) 
    implements Identifiable, Auditable, JsonSerializable {
    
    // 实现Identifiable接口
    @Override
    public String getId() {
        return id;
    }
    
    @Override
    public boolean isValid() {
        return id != null && !id.trim().isEmpty() &&
               name != null && !name.trim().isEmpty() &&
               price >= 0 && stock >= 0;
    }
    
    // 实现Auditable接口
    @Override
    public void audit() {
        System.out.printf("产品审计: %s (ID: %s, 价格: %.2f, 库存: %d)%n",
                name, id, price, stock);
    }
    
    // 实现JsonSerializable接口
    @Override
    public String toJson() {
        return String.format("""
            {
                "id": "%s",
                "name": "%s",
                "price": %.2f,
                "stock": %d
            }
            """, id, name, price, stock);
    }
    
    // 实例方法
    public Product applyDiscount(double discountRate) {
        if (discountRate < 0 || discountRate > 1) {
            throw new IllegalArgumentException("折扣率必须在0-1之间");
        }
        return new Product(id, name, price * (1 - discountRate), stock);
    }
    
    public boolean isInStock() {
        return stock > 0;
    }
    
    // 紧凑构造方法
    public Product {
        if (id == null || id.trim().isEmpty()) {
            id = generateId();
        }
        if (price < 0) {
            throw new IllegalArgumentException("价格不能为负数");
        }
        if (stock < 0) {
            throw new IllegalArgumentException("库存不能为负数");
        }
        name = name != null ? name.trim() : "未命名产品";
    }
    
    private static String generateId() {
        return "PROD_" + System.nanoTime();
    }
}

class InterfaceDemo {
    public static void main(String[] args) {
        Product product = new Product(null, "笔记本电脑", 5999.0, 10);
        
        // 作为Identifiable使用
        Identifiable identifiable = product;
        System.out.println("ID: " + identifiable.getId());
        System.out.println("是否有效: " + identifiable.isValid());
        
        // 作为Auditable使用
        Auditable auditable = product;
        auditable.audit();
        System.out.println("审计信息: " + auditable.getAuditInfo());
        
        // 作为JsonSerializable使用
        JsonSerializable serializable = product;
        System.out.println("JSON: " + serializable.toJson());
        
        // 使用记录类方法
        Product discounted = product.applyDiscount(0.1);
        System.out.println("打折后: " + discounted);
        System.out.println("是否有库存: " + discounted.isInStock());
    }
}

嵌套记录类(内部记录类和静态嵌套记录类)

import java.util.*;

// 外部类
public class University {
    private final String name;
    private final List<Department> departments;
    
    public University(String name) {
        this.name = name;
        this.departments = new ArrayList<>();
    }
    
    // 静态嵌套记录类
    public record Department(String code, String name, String dean) {
        // 紧凑构造方法
        public Department {
            if (code == null || code.length() != 4) {
                throw new IllegalArgumentException("院系代码必须是4位");
            }
            code = code.toUpperCase();
            name = name != null ? name.trim() : "";
        }
        
        // 实例方法
        public String getFullName() {
            return code + " - " + name;
        }
        
        public static Department create(String code, String name, String dean) {
            return new Department(code, name, dean);
        }
    }
    
    // 内部记录类(非静态)
    public record Course(Department department, String courseCode, String courseName, int credits) {
        // 内部记录类可以访问外部类的实例成员
        public String getUniversityInfo() {
            return "课程属于: " + University.this.name;
        }
        
        public String getFullCourseCode() {
            return department.code() + "-" + courseCode;
        }
    }
    
    // 外部类方法
    public void addDepartment(String code, String name, String dean) {
        Department dept = new Department(code, name, dean);
        departments.add(dept);
    }
    
    public List<Department> getDepartments() {
        return Collections.unmodifiableList(departments);
    }
    
    public Course createCourse(String deptCode, String courseCode, String courseName, int credits) {
        Department dept = departments.stream()
            .filter(d -> d.code().equals(deptCode))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("院系不存在: " + deptCode));
        
        return new Course(dept, courseCode, courseName, credits);
    }
}

class NestedRecordDemo {
    public static void main(String[] args) {
        University university = new University("Java大学");
        
        // 使用静态嵌套记录类
        University.Department csDept = new University.Department("CS01", "计算机科学", "张教授");
        University.Department mathDept = University.Department.create("MATH", "数学系", "李教授");
        
        university.addDepartment("CS01", "计算机科学", "张教授");
        university.addDepartment("MATH", "数学系", "李教授");
        
        System.out.println("院系: " + csDept.getFullName());
        System.out.println("院系: " + mathDept);
        
        // 使用内部记录类
        University.Course course = university.createCourse("CS01", "CS101", "Java编程", 3);
        System.out.println("课程: " + course.getFullCourseCode());
        System.out.println("课程信息: " + course.getUniversityInfo());
        
        // 遍历院系
        System.out.println("\n所有院系:");
        for (University.Department dept : university.getDepartments()) {
            System.out.println(" - " + dept.getFullName() + ", 院长: " + dept.dean());
        }
    }
}

泛型记录类(带泛型参数的记录类)

import java.util.*;
import java.util.function.*;

// 泛型记录类
public record Pair<T, U>(T first, U second) {
    // 实例方法
    public <V> Pair<V, U> mapFirst(Function<? super T, ? extends V> mapper) {
        return new Pair<>(mapper.apply(first), second);
    }
    
    public <V> Pair<T, V> mapSecond(Function<? super U, ? extends V> mapper) {
        return new Pair<>(first, mapper.apply(second));
    }
    
    public Pair<U, T> swap() {
        return new Pair<>(second, first);
    }
    
    public void forEach(BiConsumer<? super T, ? super U> action) {
        action.accept(first, second);
    }
    
    // 静态工厂方法
    public static <T, U> Pair<T, U> of(T first, U second) {
        return new Pair<>(first, second);
    }
    
    public static <T> Pair<T, T> duplicate(T value) {
        return new Pair<>(value, value);
    }
    
    // 重写toString
    @Override
    public String toString() {
        return "(" + first + ", " + second + ")";
    }
}

// 另一个泛型记录类示例
public record Result<T, E>(T value, E error, boolean success) {
    // 紧凑构造方法
    public Result {
        if (success && error != null) {
            throw new IllegalArgumentException("成功结果不能有错误信息");
        }
        if (!success && value != null) {
            throw new IllegalArgumentException("失败结果不能有值");
        }
    }
    
    // 成功工厂方法
    public static <T, E> Result<T, E> success(T value) {
        return new Result<>(value, null, true);
    }
    
    // 失败工厂方法
    public static <T, E> Result<T, E> failure(E error) {
        return new Result<>(null, error, false);
    }
    
    // 实例方法
    public T getOrElse(T defaultValue) {
        return success ? value : defaultValue;
    }
    
    public Result<T, E> map(Function<? super T, ? extends T> mapper) {
        if (!success) return this;
        return Result.success(mapper.apply(value));
    }
    
    public <U> Result<U, E> flatMap(Function<? super T, Result<U, E>> mapper) {
        if (!success) return Result.failure(error);
        return mapper.apply(value);
    }
    
    public void ifSuccess(Consumer<? super T> action) {
        if (success) {
            action.accept(value);
        }
    }
    
    public void ifFailure(Consumer<? super E> action) {
        if (!success) {
            action.accept(error);
        }
    }
}

class GenericRecordDemo {
    public static void main(String[] args) {
        // 使用Pair记录类
        Pair<String, Integer> nameAge = new Pair<>("张三", 25);
        Pair<String, String> nameUpperCase = nameAge.mapFirst(String::toUpperCase);
        Pair<Integer, String> swapped = nameAge.swap();
        
        System.out.println("原始: " + nameAge);
        System.out.println("转换: " + nameUpperCase);
        System.out.println("交换: " + swapped);
        
        nameAge.forEach((name, age) -> 
            System.out.println("姓名: " + name + ", 年龄: " + age));
        
        // 使用Result记录类
        Result<Integer, String> successResult = Result.success(42);
        Result<Integer, String> failureResult = Result.failure("计算失败");
        
        System.out.println("\n成功结果: " + successResult);
        System.out.println("失败结果: " + failureResult);
        
        successResult.ifSuccess(value -> System.out.println("成功值: " + value));
        failureResult.ifFailure(error -> System.out.println("错误: " + error));
        
        Result<Integer, String> mapped = successResult.map(x -> x * 2);
        System.out.println("映射后: " + mapped);
        
        Integer defaultValue = failureResult.getOrElse(0);
        System.out.println("默认值: " + defaultValue);
    }
}

记录类与模式匹配(instanceof 模式匹配)

// 记录类 hierarchy
sealed interface Shape permits Circle, Rectangle, Triangle {
    double area();
}

record Circle(double radius) implements Shape {
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

record Rectangle(double width, double height) implements Shape {
    @Override
    public double area() {
        return width * height;
    }
}

record Triangle(double base, double height) implements Shape {
    @Override
    public double area() {
        return 0.5 * base * height;
    }
}

// 使用模式匹配
class PatternMatchingDemo {
    public static void processShape(Shape shape) {
        // instanceof 模式匹配 (Java 16+)
        if (shape instanceof Circle c) {
            System.out.println("圆形 - 半径: " + c.radius() + ", 面积: " + c.area());
        } else if (shape instanceof Rectangle r) {
            System.out.println("矩形 - 宽: " + r.width() + ", 高: " + r.height() + ", 面积: " + r.area());
        } else if (shape instanceof Triangle t) {
            System.out.println("三角形 - 底: " + t.base() + ", 高: " + t.height() + ", 面积: " + t.area());
        }
    }
    
    // switch 表达式模式匹配 (Java 17+)
    public static String describeShape(Shape shape) {
        return switch (shape) {
            case Circle c -> "圆形(半径=" + c.radius() + ")";
            case Rectangle r -> "矩形(" + r.width() + "x" + r.height() + ")";
            case Triangle t -> "三角形(底=" + t.base() + ",高=" + t.height() + ")";
        };
    }
    
    // 嵌套模式匹配
    public static void processOptionalShape(Optional<Shape> optionalShape) {
        if (optionalShape instanceof Optional<Circle> opt && opt.isPresent()) {
            Circle c = opt.get();
            System.out.println("可选圆形: " + c.radius());
        }
    }
    
    public static void main(String[] args) {
        List<Shape> shapes = List.of(
            new Circle(5.0),
            new Rectangle(4.0, 6.0),
            new Triangle(3.0, 4.0)
        );
        
        System.out.println("处理形状:");
        for (Shape shape : shapes) {
            processShape(shape);
            System.out.println("描述: " + describeShape(shape));
            System.out.println("---");
        }
    }
}

记录类序列化

import java.io.*;
import java.util.Base64;

// 可序列化的记录类
public record UserRecord(String username, String email, int age) 
    implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // 紧凑构造方法
    public UserRecord {
        if (username == null || username.trim().isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
        username = username.trim();
    }
    
    // 自定义序列化逻辑
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        System.out.println("序列化用户: " + username);
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("反序列化用户: " + username);
    }
    
    // 静态工厂方法从序列化数据创建
    public static UserRecord fromSerializedData(byte[] data) {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            return (UserRecord) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("反序列化失败", e);
        }
    }
    
    // 转换为Base64序列化字符串
    public String toBase64() {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            oos.writeObject(this);
            return Base64.getEncoder().encodeToString(bos.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("序列化失败", e);
        }
    }
}

class SerializationDemo {
    public static void main(String[] args) {
        UserRecord user = new UserRecord("john_doe", "john@example.com", 30);
        
        try {
            // 序列化到文件
            try (FileOutputStream fos = new FileOutputStream("user.ser");
                 ObjectOutputStream oos = new ObjectOutputStream(fos)) {
                oos.writeObject(user);
            }
            
            // 从文件反序列化
            try (FileInputStream fis = new FileInputStream("user.ser");
                 ObjectInputStream ois = new ObjectInputStream(fis)) {
                UserRecord deserializedUser = (UserRecord) ois.readObject();
                System.out.println("反序列化用户: " + deserializedUser);
                System.out.println("是否相等: " + user.equals(deserializedUser));
            }
            
            // 使用Base64序列化
            String base64Data = user.toBase64();
            System.out.println("Base64数据: " + base64Data.substring(0, 50) + "...");
            
            UserRecord fromBase64 = UserRecord.fromSerializedData(
                Base64.getDecoder().decode(base64Data)
            );
            System.out.println("从Base64恢复: " + fromBase64);
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

记录类与集合框架(在集合中使用记录类)

import java.util.*;
import java.util.stream.*;

public record Student(String id, String name, int score, String className) 
    implements Comparable<Student> {
    
    // 紧凑构造方法
    public Student {
        if (score < 0 || score > 100) {
            throw new IllegalArgumentException("分数必须在0-100之间");
        }
        name = name != null ? name.trim() : "";
        className = className != null ? className.toUpperCase() : "";
    }
    
    // 实现Comparable接口
    @Override
    public int compareTo(Student other) {
        return Integer.compare(other.score, this.score); // 按分数降序
    }
    
    // 成绩等级
    public String getGrade() {
        if (score >= 90) return "A";
        else if (score >= 80) return "B";
        else if (score >= 70) return "C";
        else if (score >= 60) return "D";
        else return "F";
    }
    
    public boolean isPassing() {
        return score >= 60;
    }
}

class CollectionDemo {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student("S001", "张三", 85, "CS101"),
            new Student("S002", "李四", 92, "CS101"),
            new Student("S003", "王五", 78, "MA101"),
            new Student("S004", "赵六", 45, "MA101"),
            new Student("S005", "钱七", 67, "CS101")
        );
        
        // 使用Stream API处理记录类集合
        System.out.println("所有学生:");
        students.forEach(System.out::println);
        
        System.out.println("\n按班级分组:");
        Map<String, List<Student>> byClass = students.stream()
            .collect(Collectors.groupingBy(Student::className));
        byClass.forEach((className, classStudents) -> {
            System.out.println(className + ": " + classStudents);
        });
        
        System.out.println("\n成绩统计:");
        DoubleSummaryStatistics stats = students.stream()
            .mapToInt(Student::score)
            .summaryStatistics();
        System.out.printf("平均分: %.2f, 最高分: %d, 最低分: %d, 总数: %d%n",
            stats.getAverage(), stats.getMax(), stats.getMin(), stats.getCount());
        
        System.out.println("\n及格学生:");
        students.stream()
            .filter(Student::isPassing)
            .sorted()
            .forEach(s -> System.out.println(s.name() + " - " + s.score() + " (" + s.getGrade() + ")"));
        
        System.out.println("\n不及格学生:");
        students.stream()
            .filter(s -> !s.isPassing())
            .forEach(s -> System.out.println(s.name() + " - " + s.score()));
        
        // 使用Set(基于equals和hashCode)
        Set<Student> studentSet = new HashSet<>(students);
        System.out.println("\nSet中的学生数量: " + studentSet.size());
        
        // 使用Map(记录类作为键)
        Map<Student, String> studentNotes = new HashMap<>();
        students.forEach(s -> studentNotes.put(s, "备注: " + s.name()));
        System.out.println("\n学生备注:");
        studentNotes.forEach((student, note) -> 
            System.out.println(student.name() + ": " + note));
    }
}

设计原则

// 1. 记录类应该是不可变的数据载体
public record ImmutablePoint(int x, int y) {
    // 好的设计:只有数据,没有可变状态
    public ImmutablePoint move(int dx, int dy) {
        return new ImmutablePoint(x + dx, y + dy);
    }
}

// 2. 避免在记录类中封装复杂业务逻辑
public record SimpleData(String id, String value, long timestamp) {
    // 保持简单,只包含数据相关的方法
    public boolean isExpired() {
        return System.currentTimeMillis() - timestamp > 3600000; // 1小时
    }
}

// 3. 合理使用紧凑构造方法进行验证
public record ValidatedEmail(String value) {
    public ValidatedEmail {
        if (value == null || !value.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
            throw new IllegalArgumentException("无效的邮箱地址: " + value);
        }
        value = value.toLowerCase();
    }
}

// 4. 为记录类提供合适的工厂方法
public record Currency(String code, String name, String symbol) {
    private static final Map<String, Currency> CURRENCIES = Map.of(
        "USD", new Currency("USD", "US Dollar", "$"),
        "EUR", new Currency("EUR", "Euro", "€"),
        "JPY", new Currency("JPY", "Japanese Yen", "¥")
    );
    
    public static Currency of(String code) {
        Currency currency = CURRENCIES.get(code.toUpperCase());
        if (currency == null) {
            throw new IllegalArgumentException("未知货币代码: " + code);
        }
        return currency;
    }
    
    public static Set<String> availableCurrencies() {
        return CURRENCIES.keySet();
    }
}

// 5. 记录类与模式匹配结合使用
class BestPracticesDemo {
    public static void processData(Object data) {
        switch (data) {
            case SimpleData sd -> System.out.println("简单数据: " + sd.value());
            case ValidatedEmail email -> System.out.println("验证邮箱: " + email.value());
            case Currency currency -> System.out.println("货币: " + currency.name());
            case null -> System.out.println("空数据");
            default -> System.out.println("未知数据类型");
        }
    }
    
    public static void main(String[] args) {
        processData(new SimpleData("1", "测试", System.currentTimeMillis()));
        processData(new ValidatedEmail("test@example.com"));
        processData(Currency.of("USD"));
        processData(null);
    }
}

总结

Java记录类的核心要点:

  1. 定义:使用record关键字,自动生成不可变数据类
  2. 自动生成:字段、构造方法、访问器、equals、hashCode、toString
  3. 紧凑构造方法:用于参数验证和规范化,无需显式赋值
  4. 自定义构造方法:必须调用主构造方法
  5. 方法支持:可以定义实例方法、静态方法、重写访问器
  6. 接口实现:可以实现多个接口
  7. 泛型支持:可以是泛型记录类
  8. 序列化:支持序列化,可以自定义序列化逻辑
  9. 模式匹配:与instanceof和switch模式匹配完美配合
  10. 不可变性:记录类本质上是不可变的
posted @ 2025-09-29 17:48  Charlie_Byte  阅读(29)  评论(0)    收藏  举报