Skip to content

Java 面向对象高级特性

在掌握了Java基础的面向对象概念之后,我们现在来深入学习一些更高级的特性,这些特性将帮助您编写更加灵活和强大的Java程序。

抽象类与接口

抽象类

抽象类是不能被实例化的类,通常包含一个或多个抽象方法。抽象方法是没有实现的方法,必须在子类中被重写。

java
// 抽象类
abstract class Animal {
    protected String name;
    protected int age;
    
    // 构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 普通方法
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
    
    // 抽象方法 - 没有方法体,必须在子类中实现
    public abstract void makeSound();
    
    public abstract void move();
    
    // getter方法
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
}

// 具体子类
class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);
        this.breed = breed;
    }
    
    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + "汪汪叫");
    }
    
    @Override
    public void move() {
        System.out.println(name + "四脚奔跑");
    }
    
    // 子类特有方法
    public void wagTail() {
        System.out.println(name + "摇尾巴");
    }
    
    public String getBreed() {
        return breed;
    }
}

class Bird extends Animal {
    private double wingSpan;
    
    public Bird(String name, int age, double wingSpan) {
        super(name, age);
        this.wingSpan = wingSpan;
    }
    
    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + "啾啾叫");
    }
    
    @Override
    public void move() {
        System.out.println(name + "展翅飞翔");
    }
    
    // 子类特有方法
    public void fly() {
        System.out.println(name + "在天空中自由飞翔,翼展" + wingSpan + "米");
    }
    
    public double getWingSpan() {
        return wingSpan;
    }
}

// 抽象类的使用示例
public class AbstractClassExample {
    public static void main(String[] args) {
        // 不能直接实例化抽象类
        // Animal animal = new Animal("动物", 5); // 编译错误
        
        // 可以实例化具体子类
        Dog dog = new Dog("旺财", 3, "金毛");
        Bird bird = new Bird("小鸟", 1, 0.5);
        
        // 调用方法
        dog.makeSound();
        dog.move();
        dog.wagTail();
        dog.sleep();
        
        System.out.println();
        
        bird.makeSound();
        bird.move();
        bird.fly();
        bird.sleep();
        
        // 多态的体现
        Animal[] animals = {
            new Dog("小白", 2, "哈士奇"),
            new Bird("小黄", 1, 0.3)
        };
        
        System.out.println("\n=== 多态示例 ===");
        for (Animal animal : animals) {
            animal.makeSound();
            animal.move();
            animal.sleep();
            System.out.println();
        }
    }
}

接口

接口是一种完全抽象的类,它只包含常量和抽象方法(Java 8之后还可以包含默认方法和静态方法)。

java
// 基础接口
interface Drawable {
    // 常量(默认是public static final)
    String DEFAULT_COLOR = "黑色";
    
    // 抽象方法(默认是public abstract)
    void draw();
    
    // 默认方法(Java 8+)
    default void display() {
        System.out.println("显示图形");
    }
    
    // 静态方法(Java 8+)
    static void info() {
        System.out.println("这是Drawable接口");
    }
    
    // 私有方法(Java 9+)
    private void helper() {
        System.out.println("辅助方法");
    }
    
    // 私有静态方法(Java 9+)
    private static void staticHelper() {
        System.out.println("静态辅助方法");
    }
}

// 另一个接口
interface Resizable {
    void resize(double factor);
    
    default void resetSize() {
        resize(1.0);
        System.out.println("重置大小");
    }
}

// 可旋转接口
interface Rotatable {
    void rotate(double angle);
    
    default void resetRotation() {
        rotate(0);
        System.out.println("重置旋转");
    }
}

// 实现单个接口
class Circle implements Drawable {
    private double radius;
    private String color;
    
    public Circle(double radius) {
        this.radius = radius;
        this.color = DEFAULT_COLOR;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制一个半径为" + radius + "的" + color + "圆形");
    }
    
    public double getRadius() {
        return radius;
    }
    
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
}

// 实现多个接口
class Rectangle implements Drawable, Resizable {
    private double width;
    private double height;
    private String color;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
        this.color = DEFAULT_COLOR;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制一个" + width + "x" + height + "的" + color + "矩形");
    }
    
    @Override
    public void resize(double factor) {
        this.width *= factor;
        this.height *= factor;
        System.out.println("矩形大小调整为: " + width + "x" + height);
    }
    
    public double getWidth() {
        return width;
    }
    
    public double getHeight() {
        return height;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
}

// 实现三个接口
class Image implements Drawable, Resizable, Rotatable {
    private String fileName;
    private double width;
    private double height;
    private double rotation;
    
    public Image(String fileName, double width, double height) {
        this.fileName = fileName;
        this.width = width;
        this.height = height;
        this.rotation = 0;
    }
    
    @Override
    public void draw() {
        System.out.println("显示图片: " + fileName + " (" + width + "x" + height + ") 旋转" + rotation + "度");
    }
    
    @Override
    public void resize(double factor) {
        this.width *= factor;
        this.height *= factor;
        System.out.println("图片大小调整为: " + width + "x" + height);
    }
    
    @Override
    public void rotate(double angle) {
        this.rotation = angle;
        System.out.println("图片旋转到: " + rotation + "度");
    }
    
    public String getFileName() {
        return fileName;
    }
    
    public double getWidth() {
        return width;
    }
    
    public double getHeight() {
        return height;
    }
    
    public double getRotation() {
        return rotation;
    }
}

// 接口的使用示例
public class InterfaceExample {
    public static void main(String[] args) {
        // 使用接口引用指向实现类对象
        Drawable circle = new Circle(5.0);
        Drawable rectangle = new Rectangle(10.0, 8.0);
        Drawable image = new Image("photo.jpg", 800, 600);
        
        // 调用接口方法
        circle.draw();
        rectangle.draw();
        image.draw();
        
        System.out.println();
        
        // 调用默认方法
        circle.display();
        rectangle.display();
        image.display();
        
        System.out.println();
        
        // 调用静态方法
        Drawable.info();
        
        System.out.println();
        
        // 多态的体现
        Drawable[] drawables = {
            new Circle(3.0),
            new Rectangle(5.0, 4.0),
            new Image("screenshot.png", 1920, 1080)
        };
        
        System.out.println("=== 绘图示例 ===");
        for (Drawable drawable : drawables) {
            drawable.draw();
            drawable.display();
            System.out.println();
        }
        
        // 使用Resizable接口
        if (rectangle instanceof Resizable) {
            Resizable resizable = (Resizable) rectangle;
            resizable.resize(1.5);
            resizable.resetSize();
        }
        
        // 使用Rotatable接口
        if (image instanceof Rotatable) {
            Rotatable rotatable = (Rotatable) image;
            rotatable.rotate(45);
            rotatable.resetRotation();
        }
    }
}

抽象类与接口的区别

java
// 抽象类示例
abstract class Vehicle {
    protected String brand;
    protected String model;
    
    public Vehicle(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }
    
    // 具体方法
    public void startEngine() {
        System.out.println(brand + " " + model + " 引擎启动");
    }
    
    // 抽象方法
    public abstract void accelerate();
    public abstract void brake();
    
    // getter方法
    public String getBrand() { return brand; }
    public String getModel() { return model; }
}

// 接口示例
interface Flyable {
    void fly();
    void land();
}

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

// 具体实现类 - 继承抽象类并实现接口
class AmphibiousVehicle extends Vehicle implements Swimmable {
    public AmphibiousVehicle(String brand, String model) {
        super(brand, model);
    }
    
    @Override
    public void accelerate() {
        System.out.println(brand + " " + model + " 在陆地上加速");
    }
    
    @Override
    public void brake() {
        System.out.println(brand + " " + model + " 在陆地上刹车");
    }
    
    @Override
    public void swim() {
        System.out.println(brand + " " + model + " 在水中游泳");
    }
    
    @Override
    public void dive() {
        System.out.println(brand + " " + model + " 潜入水中");
    }
}

// 飞行器类 - 实现多个接口
class FlyingCar extends Vehicle implements Flyable {
    private int altitude;
    
    public FlyingCar(String brand, String model) {
        super(brand, model);
        this.altitude = 0;
    }
    
    @Override
    public void accelerate() {
        System.out.println(brand + " " + model + " 在地面加速");
    }
    
    @Override
    public void brake() {
        System.out.println(brand + " " + model + " 在地面刹车");
    }
    
    @Override
    public void fly() {
        this.altitude = 1000;
        System.out.println(brand + " " + model + " 飞行在" + altitude + "米高空");
    }
    
    @Override
    public void land() {
        this.altitude = 0;
        System.out.println(brand + " " + model + " 安全着陆");
    }
    
    public int getAltitude() {
        return altitude;
    }
}

// 水陆空三栖载具 - 继承抽象类并实现多个接口
class AmphibiousFlyingVehicle extends Vehicle implements Swimmable, Flyable {
    private int altitude;
    
    public AmphibiousFlyingVehicle(String brand, String model) {
        super(brand, model);
        this.altitude = 0;
    }
    
    @Override
    public void accelerate() {
        System.out.println(brand + " " + model + " 在地面加速");
    }
    
    @Override
    public void brake() {
        System.out.println(brand + " " + model + " 在地面刹车");
    }
    
    @Override
    public void swim() {
        System.out.println(brand + " " + model + " 在水中游泳");
    }
    
    @Override
    public void dive() {
        System.out.println(brand + " " + model + " 潜入水中");
    }
    
    @Override
    public void fly() {
        this.altitude = 2000;
        System.out.println(brand + " " + model + " 飞行在" + altitude + "米高空");
    }
    
    @Override
    public void land() {
        this.altitude = 0;
        System.out.println(brand + " " + model + " 安全着陆");
    }
    
    public int getAltitude() {
        return altitude;
    }
}

// 比较示例
public class AbstractVsInterface {
    public static void main(String[] args) {
        System.out.println("=== 抽象类与接口比较示例 ===");
        
        // 创建不同类型的载具
        AmphibiousVehicle amphibious = new AmphibiousVehicle("Gibbs", "Aquada");
        FlyingCar flyingCar = new FlyingCar("Terrafugia", "Transition");
        AmphibiousFlyingVehicle hybrid = new AmphibiousFlyingVehicle("Future", "Hybrid");
        
        // 使用Vehicle引用(抽象类)
        Vehicle[] vehicles = {amphibious, flyingCar, hybrid};
        
        System.out.println("\n--- 载具基本操作 ---");
        for (Vehicle vehicle : vehicles) {
            System.out.println("\n载具: " + vehicle.getBrand() + " " + vehicle.getModel());
            vehicle.startEngine();
            vehicle.accelerate();
            vehicle.brake();
        }
        
        // 使用Swimmable接口
        System.out.println("\n--- 水中操作 ---");
        if (amphibious instanceof Swimmable) {
            Swimmable swimmer = amphibious;
            swimmer.swim();
            swimmer.dive();
        }
        
        if (hybrid instanceof Swimmable) {
            Swimmable swimmer = hybrid;
            swimmer.swim();
        }
        
        // 使用Flyable接口
        System.out.println("\n--- 飞行操作 ---");
        if (flyingCar instanceof Flyable) {
            Flyable flyer = flyingCar;
            flyer.fly();
            flyer.land();
        }
        
        if (hybrid instanceof Flyable) {
            Flyable flyer = hybrid;
            flyer.fly();
            flyer.land();
        }
        
        // 多接口的多态
        System.out.println("\n--- 多态示例 ---");
        Swimmable[] swimmers = {amphibious, hybrid};
        for (Swimmable swimmer : swimmers) {
            swimmer.swim();
        }
        
        Flyable[] flyers = {flyingCar, hybrid};
        for (Flyable flyer : flyers) {
            flyer.fly();
        }
    }
}

静态成员与 final 关键字

静态成员

静态成员属于类本身,而不是类的实例。它们在类加载时初始化,所有实例共享同一份静态成员。

java
public class StaticExample {
    // 静态变量 - 类变量
    private static int instanceCount = 0;
    private static final String COMPANY_NAME = "Java技术公司";
    
    // 实例变量
    private String name;
    private int id;
    
    // 静态代码块 - 类加载时执行
    static {
        System.out.println("静态代码块执行");
        System.out.println("公司名称: " + COMPANY_NAME);
    }
    
    // 实例代码块 - 每次创建实例时执行
    {
        System.out.println("实例代码块执行");
        instanceCount++;
        this.id = instanceCount;
    }
    
    // 构造方法
    public StaticExample(String name) {
        System.out.println("构造方法执行");
        this.name = name;
    }
    
    // 静态方法
    public static int getInstanceCount() {
        return instanceCount;
    }
    
    public static String getCompanyName() {
        return COMPANY_NAME;
    }
    
    // 静态方法不能直接访问实例成员
    public static void staticMethod() {
        System.out.println("这是静态方法");
        System.out.println("公司名称: " + COMPANY_NAME);
        // System.out.println(name); // 编译错误 - 不能访问实例变量
        // instanceMethod(); // 编译错误 - 不能直接调用实例方法
    }
    
    // 实例方法
    public void instanceMethod() {
        System.out.println("这是实例方法");
        System.out.println("姓名: " + name);
        System.out.println("ID: " + id);
        System.out.println("实例计数: " + instanceCount); // 可以访问静态变量
        staticMethod(); // 可以调用静态方法
    }
    
    // getter方法
    public String getName() {
        return name;
    }
    
    public int getId() {
        return id;
    }
    
    // 重写toString方法
    @Override
    public String toString() {
        return "StaticExample{name='" + name + "', id=" + id + "}";
    }
    
    public static void main(String[] args) {
        System.out.println("=== 静态成员示例 ===");
        
        // 访问静态变量和方法不需要创建实例
        System.out.println("初始实例计数: " + StaticExample.getInstanceCount());
        System.out.println("公司名称: " + StaticExample.getCompanyName());
        
        // 调用静态方法
        StaticExample.staticMethod();
        
        System.out.println("\n--- 创建实例 ---");
        // 创建实例
        StaticExample obj1 = new StaticExample("对象1");
        StaticExample obj2 = new StaticExample("对象2");
        StaticExample obj3 = new StaticExample("对象3");
        
        System.out.println("\n--- 实例信息 ---");
        System.out.println("obj1: " + obj1);
        System.out.println("obj2: " + obj2);
        System.out.println("obj3: " + obj3);
        
        System.out.println("\n最终实例计数: " + StaticExample.getInstanceCount());
        
        System.out.println("\n--- 调用实例方法 ---");
        obj1.instanceMethod();
        System.out.println();
        obj2.instanceMethod();
    }
}

// 静态导入示例
import static java.lang.Math.*;
import static java.lang.System.*;

class StaticImportExample {
    public static void main(String[] args) {
        // 使用静态导入后可以直接使用Math和System的静态成员
        double result = sqrt(pow(3, 2) + pow(4, 2));
        out.println("3² + 4² 的平方根 = " + result);
        
        out.println("π = " + PI);
        out.println("随机数 = " + random());
    }
}

final 关键字

final关键字可以用于变量、方法和类,表示它们是不可改变的。

java
// final类 - 不能被继承
final class Constants {
    // final变量 - 常量,只能赋值一次
    public static final double PI = 3.141592653589793;
    public static final String COMPANY_NAME = "Java技术公司";
    public final String VERSION = "1.0.0";
    
    // final方法 - 不能被重写
    public final void displayInfo() {
        System.out.println("公司: " + COMPANY_NAME);
        System.out.println("版本: " + VERSION);
    }
}

// 普通类
class MathUtils {
    // final实例变量 - 每个实例只能赋值一次
    private final double radius;
    private final String shapeType;
    
    public MathUtils(double radius, String shapeType) {
        this.radius = radius;
        this.shapeType = shapeType;
    }
    
    // final方法 - 不能被重写
    public final double calculateArea() {
        switch (shapeType.toLowerCase()) {
            case "circle":
                return Constants.PI * radius * radius;
            case "square":
                return radius * radius;
            default:
                return 0;
        }
    }
    
    // 非final方法 - 可以被重写
    public void displayShapeInfo() {
        System.out.println("形状: " + shapeType);
        System.out.println("半径/边长: " + radius);
        System.out.println("面积: " + calculateArea());
    }
    
    // getter方法
    public double getRadius() {
        return radius;
    }
    
    public String getShapeType() {
        return shapeType;
    }
}

// 继承MathUtils类
class AdvancedMathUtils extends MathUtils {
    private final double height;
    
    public AdvancedMathUtils(double radius, String shapeType, double height) {
        super(radius, shapeType);
        this.height = height;
    }
    
    // 重写非final方法
    @Override
    public void displayShapeInfo() {
        super.displayShapeInfo();
        System.out.println("高度: " + height);
        System.out.println("体积: " + calculateVolume());
    }
    
    // 不能重写final方法
    // public final double calculateArea() { } // 编译错误
    
    // 计算体积
    public double calculateVolume() {
        return calculateArea() * height;
    }
    
    public double getHeight() {
        return height;
    }
}

// final类 - 不能被继承
final class UtilityClass {
    // 私有构造方法 - 防止实例化
    private UtilityClass() {
        // 私有构造方法防止外部实例化
    }
    
    // 静态工具方法
    public static int max(int a, int b) {
        return a > b ? a : b;
    }
    
    public static int min(int a, int b) {
        return a < b ? a : b;
    }
    
    public static boolean isEven(int number) {
        return number % 2 == 0;
    }
    
    public static boolean isOdd(int number) {
        return number % 2 != 0;
    }
}

// final参数示例
class ParameterExample {
    // final参数 - 方法内不能修改参数值
    public void processString(final String text) {
        System.out.println("处理文本: " + text);
        // text = "新值"; // 编译错误 - 不能修改final参数
    }
    
    public void processArray(final int[] numbers) {
        System.out.println("数组长度: " + numbers.length);
        // numbers = new int[5]; // 编译错误 - 不能修改final数组引用
        numbers[0] = 100; // 可以修改数组元素 - final只保护引用
        System.out.println("修改后第一个元素: " + numbers[0]);
    }
}

// final示例
public class FinalExample {
    public static void main(String[] args) {
        System.out.println("=== final关键字示例 ===");
        
        // 使用final常量
        System.out.println("π = " + Constants.PI);
        System.out.println("公司名称: " + Constants.COMPANY_NAME);
        
        // 使用final类
        Constants constants = new Constants();
        constants.displayInfo();
        
        System.out.println("\n--- final变量示例 ---");
        // final局部变量
        final int MAX_SIZE = 100;
        System.out.println("最大尺寸: " + MAX_SIZE);
        // MAX_SIZE = 200; // 编译错误 - 不能修改final变量
        
        System.out.println("\n--- final方法示例 ---");
        MathUtils circle = new MathUtils(5.0, "circle");
        circle.displayShapeInfo();
        
        System.out.println();
        AdvancedMathUtils cylinder = new AdvancedMathUtils(3.0, "circle", 10.0);
        cylinder.displayShapeInfo();
        
        System.out.println("\n--- final类示例 ---");
        System.out.println("最大值: " + UtilityClass.max(10, 20));
        System.out.println("最小值: " + UtilityClass.min(10, 20));
        System.out.println("10是偶数: " + UtilityClass.isEven(10));
        System.out.println("15是奇数: " + UtilityClass.isOdd(15));
        
        System.out.println("\n--- final参数示例 ---");
        ParameterExample paramExample = new ParameterExample();
        paramExample.processString("Hello World");
        
        int[] array = {1, 2, 3, 4, 5};
        System.out.println("修改前数组: " + java.util.Arrays.toString(array));
        paramExample.processArray(array);
        System.out.println("修改后数组: " + java.util.Arrays.toString(array));
    }
}

内部类与匿名类

内部类

内部类是定义在另一个类内部的类,它可以访问外部类的所有成员。

java
// 外部类
public class OuterClass {
    private String outerField = "外部类字段";
    private static String staticOuterField = "静态外部类字段";
    
    // 1. 成员内部类
    class InnerClass {
        private String innerField = "内部类字段";
        
        public void innerMethod() {
            System.out.println("=== 成员内部类方法 ===");
            System.out.println("访问内部类字段: " + innerField);
            System.out.println("访问外部类字段: " + outerField);
            System.out.println("访问静态外部类字段: " + staticOuterField);
            
            // 可以直接访问外部类的所有成员
            outerMethod();
            staticOuterMethod();
        }
        
        public String getInnerField() {
            return innerField;
        }
    }
    
    // 2. 静态内部类
    static class StaticInnerClass {
        private String staticInnerField = "静态内部类字段";
        
        public void staticInnerMethod() {
            System.out.println("=== 静态内部类方法 ===");
            System.out.println("访问静态内部类字段: " + staticInnerField);
            System.out.println("访问静态外部类字段: " + staticOuterField);
            // System.out.println(outerField); // 编译错误 - 不能访问非静态外部类成员
            staticOuterMethod();
        }
        
        public String getStaticInnerField() {
            return staticInnerField;
        }
    }
    
    // 3. 局部内部类
    public void methodWithLocalClass() {
        final String localVar = "局部变量";
        final int localNumber = 42;
        
        // 局部内部类
        class LocalInnerClass {
            private String localInnerField = "局部内部类字段";
            
            public void localInnerMethod() {
                System.out.println("=== 局部内部类方法 ===");
                System.out.println("访问局部内部类字段: " + localInnerField);
                System.out.println("访问外部类字段: " + outerField);
                System.out.println("访问局部变量: " + localVar);
                System.out.println("访问局部数字: " + localNumber);
            }
        }
        
        // 在方法内创建和使用局部内部类
        LocalInnerClass localInner = new LocalInnerClass();
        localInner.localInnerMethod();
    }
    
    // 外部类方法
    public void outerMethod() {
        System.out.println("外部类方法被调用");
    }
    
    // 静态外部类方法
    public static void staticOuterMethod() {
        System.out.println("静态外部类方法被调用");
    }
    
    // 创建内部类实例的方法
    public InnerClass createInnerClass() {
        return new InnerClass();
    }
    
    // getter方法
    public String getOuterField() {
        return outerField;
    }
}

// 接口定义
interface Drawable {
    void draw();
}

interface Clickable {
    void click();
}

// 使用内部类的实际示例
class Button {
    private String label;
    private int x, y, width, height;
    
    public Button(String label, int x, int y, int width, int height) {
        this.label = label;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    
    // 成员内部类 - 事件处理器
    class ButtonHandler implements Drawable, Clickable {
        @Override
        public void draw() {
            System.out.println("绘制按钮: " + label + " 位置(" + x + "," + y + ") 尺寸(" + width + "x" + height + ")");
        }
        
        @Override
        public void click() {
            System.out.println("按钮 '" + label + "' 被点击了!");
        }
        
        // 内部类特有方法
        public void hover() {
            System.out.println("鼠标悬停在按钮 '" + label + "' 上");
        }
    }
    
    // 获取事件处理器
    public ButtonHandler getHandler() {
        return new ButtonHandler();
    }
    
    // 简化方法
    public void draw() {
        getHandler().draw();
    }
    
    public void click() {
        getHandler().click();
    }
}

// 内部类示例
public class InnerClassExample {
    public static void main(String[] args) {
        System.out.println("=== 内部类示例 ===");
        
        // 1. 成员内部类
        System.out.println("--- 成员内部类 ---");
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.createInnerClass();
        inner.innerMethod();
        
        // 另一种创建方式
        OuterClass.InnerClass inner2 = outer.new InnerClass();
        System.out.println("内部类字段: " + inner2.getInnerField());
        
        // 2. 静态内部类
        System.out.println("\n--- 静态内部类 ---");
        OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
        staticInner.staticInnerMethod();
        System.out.println("静态内部类字段: " + staticInner.getStaticInnerField());
        
        // 3. 局部内部类
        System.out.println("\n--- 局部内部类 ---");
        outer.methodWithLocalClass();
        
        // 4. 实际应用示例
        System.out.println("\n--- 实际应用示例 ---");
        Button button = new Button("提交", 100, 200, 80, 30);
        button.draw();
        
        Button.ButtonHandler handler = button.getHandler();
        handler.click();
        handler.hover();
        
        // 使用接口引用
        Drawable drawable = button.getHandler();
        drawable.draw();
        
        Clickable clickable = button.getHandler();
        clickable.click();
    }
}

匿名类

匿名类是没有名字的内部类,通常用于创建只需要使用一次的类实例。

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

interface Calculator {
    int calculate(int a, int b);
}

// 抽象类
abstract class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public abstract void makeSound();
    
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

// 匿名类示例
public class AnonymousClassExample {
    public static void main(String[] args) {
        System.out.println("=== 匿名类示例 ===");
        
        // 1. 匿名类实现接口
        System.out.println("--- 匿名类实现接口 ---");
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("你好,世界!");
            }
        };
        greeting.sayHello();
        
        // 2. 匿名类实现多个方法的接口
        Calculator adder = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };
        
        Calculator multiplier = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a * b;
            }
        };
        
        System.out.println("5 + 3 = " + adder.calculate(5, 3));
        System.out.println("5 * 3 = " + multiplier.calculate(5, 3));
        
        // 3. 匿名类继承抽象类
        System.out.println("\n--- 匿名类继承抽象类 ---");
        Animal dog = new Animal("旺财") {
            @Override
            public void makeSound() {
                System.out.println(name + "汪汪叫");
            }
            
            // 可以添加额外方法
            public void wagTail() {
                System.out.println(name + "摇尾巴");
            }
        };
        
        dog.makeSound();
        dog.sleep();
        // dog.wagTail(); // 编译错误 - 父类引用无法访问子类特有方法
        
        // 4. 匿名类继承具体类
        System.out.println("\n--- 匿名类继承具体类 ---");
        String message = "匿名类示例";
        Object obj = new Object() {
            // 可以访问外部类的final或effectively final变量
            public void displayMessage() {
                System.out.println("消息: " + message);
            }
            
            @Override
            public String toString() {
                return "匿名类对象: " + message;
            }
        };
        
        // 使用反射调用匿名类的特有方法
        try {
            obj.getClass().getMethod("displayMessage").invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        System.out.println(obj.toString());
        
        // 5. 在方法参数中使用匿名类
        System.out.println("\n--- 在方法参数中使用匿名类 ---");
        processGreeting(new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("在方法中使用匿名类打招呼");
            }
        });
        
        // 6. 匿名类与事件处理(模拟)
        System.out.println("\n--- 匿名类与事件处理 ---");
        simulateButtonEvent();
        
        // 7. 匿名类与多线程
        System.out.println("\n--- 匿名类与多线程 ---");
        simulateThread();
    }
    
    // 处理问候的方法
    public static void processGreeting(Greeting greeting) {
        System.out.println("处理问候:");
        greeting.sayHello();
    }
    
    // 模拟按钮事件
    public static void simulateButtonEvent() {
        // 模拟按钮点击事件处理
        EventHandler clickHandler = new EventHandler() {
            @Override
            public void handle() {
                System.out.println("按钮被点击了!");
            }
        };
        
        EventHandler hoverHandler = new EventHandler() {
            @Override
            public void handle() {
                System.out.println("鼠标悬停在按钮上");
            }
        };
        
        // 触发事件
        clickHandler.handle();
        hoverHandler.handle();
    }
    
    // 模拟多线程
    public static void simulateThread() {
        // 使用匿名类创建线程
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 3; i++) {
                    System.out.println("线程1执行: " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 3; i++) {
                    System.out.println("线程2执行: " + i);
                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        // 等待线程完成
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("所有线程执行完成");
    }
}

// 事件处理器接口
interface EventHandler {
    void handle();
}

// 实际应用示例:计算器应用
class CalculatorApp {
    public static void main(String[] args) {
        System.out.println("=== 计算器应用示例 ===");
        
        // 创建不同的计算器操作
        Calculator[] operations = {
            new Calculator() {
                @Override
                public int calculate(int a, int b) {
                    return a + b;
                }
            },
            new Calculator() {
                @Override
                public int calculate(int a, int b) {
                    return a - b;
                }
            },
            new Calculator() {
                @Override
                public int calculate(int a, int b) {
                    return a * b;
                }
            },
            new Calculator() {
                @Override
                public int calculate(int a, int b) {
                    return b != 0 ? a / b : 0;
                }
            }
        };
        
        String[] operationNames = {"加法", "减法", "乘法", "除法"};
        int a = 20, b = 4;
        
        System.out.println("计算 " + a + " 和 " + b + " 的结果:");
        for (int i = 0; i < operations.length; i++) {
            int result = operations[i].calculate(a, b);
            System.out.println(operationNames[i] + ": " + result);
        }
    }
}

反射机制

反射机制允许程序在运行时检查和操作类、接口、字段和方法,而不需要在编译时知道它们的名称。

java
import java.lang.reflect.*;

// 示例类用于反射演示
class Person {
    private String name;
    private int age;
    public String email;
    
    // 构造方法
    public Person() {
        this.name = "未知";
        this.age = 0;
        this.email = "unknown@example.com";
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        this.email = name.toLowerCase().replace(" ", "") + "@example.com";
    }
    
    public Person(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
    
    // 公共方法
    public void introduce() {
        System.out.println("大家好,我叫" + name + ",今年" + age + "岁");
    }
    
    public void work(String job) {
        System.out.println(name + "正在从事" + job + "工作");
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
    
    // 私有方法
    private void secretMethod() {
        System.out.println("这是一个私有方法,只有通过反射才能调用");
    }
    
    // 静态方法
    public static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", email='" + email + "'}";
    }
}

// 注解用于反射演示
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
    String value() default "";
    int priority() default 1;
}

// 带注解的类
class AnnotatedClass {
    @MyAnnotation(value = "重要方法", priority = 10)
    public void importantMethod() {
        System.out.println("重要方法被调用");
    }
    
    @MyAnnotation(value = "普通方法", priority = 5)
    public void normalMethod() {
        System.out.println("普通方法被调用");
    }
    
    @Deprecated
    public void deprecatedMethod() {
        System.out.println("过时方法被调用");
    }
}

// 反射机制示例
public class ReflectionExample {
    public static void main(String[] args) {
        System.out.println("=== Java反射机制示例 ===");
        
        try {
            // 1. 获取Class对象的三种方式
            System.out.println("--- 获取Class对象 ---");
            Class<?> class1 = Person.class;  // 类字面量
            Class<?> class2 = new Person().getClass();  // getClass()方法
            Class<?> class3 = Class.forName("Person");  // forName()方法
            
            System.out.println("Class1: " + class1.getName());
            System.out.println("Class2: " + class2.getName());
            System.out.println("Class3: " + class3.getName());
            
            // 2. 获取类的基本信息
            System.out.println("\n--- 类的基本信息 ---");
            getClassInfo(class1);
            
            // 3. 获取构造方法
            System.out.println("\n--- 构造方法信息 ---");
            getConstructors(class1);
            
            // 4. 获取方法
            System.out.println("\n--- 方法信息 ---");
            getMethods(class1);
            
            // 5. 获取字段
            System.out.println("\n--- 字段信息 ---");
            getFields(class1);
            
            // 6. 创建对象实例
            System.out.println("\n--- 创建对象实例 ---");
            createInstance(class1);
            
            // 7. 调用方法
            System.out.println("\n--- 调用方法 ---");
            invokeMethods(class1);
            
            // 8. 访问私有成员
            System.out.println("\n--- 访问私有成员 ---");
            accessPrivateMembers(class1);
            
            // 9. 处理注解
            System.out.println("\n--- 处理注解 ---");
            handleAnnotations();
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 获取类的基本信息
    public static void getClassInfo(Class<?> clazz) {
        System.out.println("类名: " + clazz.getSimpleName());
        System.out.println("完整类名: " + clazz.getName());
        System.out.println("包名: " + clazz.getPackage().getName());
        System.out.println("是否为接口: " + clazz.isInterface());
        System.out.println("是否为数组: " + clazz.isArray());
        System.out.println("父类: " + (clazz.getSuperclass() != null ? clazz.getSuperclass().getName() : "无"));
        
        // 获取实现的接口
        Class<?>[] interfaces = clazz.getInterfaces();
        if (interfaces.length > 0) {
            System.out.println("实现的接口:");
            for (Class<?> intf : interfaces) {
                System.out.println("  " + intf.getName());
            }
        }
    }
    
    // 获取构造方法信息
    public static void getConstructors(Class<?> clazz) throws Exception {
        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println("公共构造方法数量: " + constructors.length);
        
        for (Constructor<?> constructor : constructors) {
            System.out.println("构造方法: " + constructor.getName());
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            System.out.print("参数类型: ");
            for (int i = 0; i < parameterTypes.length; i++) {
                if (i > 0) System.out.print(", ");
                System.out.print(parameterTypes[i].getSimpleName());
            }
            System.out.println();
        }
    }
    
    // 获取方法信息
    public static void getMethods(Class<?> clazz) {
        // 获取所有公共方法(包括继承的)
        Method[] methods = clazz.getMethods();
        System.out.println("公共方法数量: " + methods.length);
        
        // 获取本类声明的所有方法(包括私有方法)
        Method[] declaredMethods = clazz.getDeclaredMethods();
        System.out.println("本类声明的方法数量: " + declaredMethods.length);
        
        System.out.println("方法列表:");
        for (Method method : declaredMethods) {
            System.out.print("  " + method.getName() + "(");
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                if (i > 0) System.out.print(", ");
                System.out.print(parameterTypes[i].getSimpleName());
            }
            System.out.println(") : " + method.getReturnType().getSimpleName());
            System.out.println("    修饰符: " + Modifier.toString(method.getModifiers()));
        }
    }
    
    // 获取字段信息
    public static void getFields(Class<?> clazz) {
        // 获取所有公共字段(包括继承的)
        Field[] fields = clazz.getFields();
        System.out.println("公共字段数量: " + fields.length);
        
        // 获取本类声明的所有字段(包括私有字段)
        Field[] declaredFields = clazz.getDeclaredFields();
        System.out.println("本类声明的字段数量: " + declaredFields.length);
        
        System.out.println("字段列表:");
        for (Field field : declaredFields) {
            System.out.println("  " + field.getName() + " : " + field.getType().getSimpleName());
            System.out.println("    修饰符: " + Modifier.toString(field.getModifiers()));
        }
    }
    
    // 创建对象实例
    public static void createInstance(Class<?> clazz) throws Exception {
        // 使用默认构造方法创建实例
        Object obj1 = clazz.newInstance();
        System.out.println("使用默认构造方法创建: " + obj1);
        
        // 使用指定构造方法创建实例
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object obj2 = constructor.newInstance("张三", 25);
        System.out.println("使用指定构造方法创建: " + obj2);
        
        // 使用带参数的构造方法创建实例
        Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class, String.class);
        Object obj3 = constructor2.newInstance("李四", 30, "lisi@example.com");
        System.out.println("使用带参数的构造方法创建: " + obj3);
    }
    
    // 调用方法
    public static void invokeMethods(Class<?> clazz) throws Exception {
        // 创建实例
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object obj = constructor.newInstance("王五", 28);
        
        // 调用无参方法
        Method introduceMethod = clazz.getMethod("introduce");
        introduceMethod.invoke(obj);
        
        // 调用带参方法
        Method workMethod = clazz.getMethod("work", String.class);
        workMethod.invoke(obj, "软件开发");
        
        // 调用getter方法
        Method getNameMethod = clazz.getMethod("getName");
        String name = (String) getNameMethod.invoke(obj);
        System.out.println("获取到的名字: " + name);
        
        // 调用setter方法
        Method setAgeMethod = clazz.getMethod("setAge", int.class);
        setAgeMethod.invoke(obj, 29);
        
        Method getAgeMethod = clazz.getMethod("getAge");
        int age = (Integer) getAgeMethod.invoke(obj);
        System.out.println("设置后的年龄: " + age);
        
        // 调用静态方法
        Method staticMethod = clazz.getMethod("staticMethod");
        staticMethod.invoke(null); // 静态方法传入null作为对象
    }
    
    // 访问私有成员
    public static void accessPrivateMembers(Class<?> clazz) throws Exception {
        // 创建实例
        Object obj = clazz.newInstance();
        
        // 访问私有字段
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true); // 设置可访问
        nameField.set(obj, "通过反射修改的名字");
        
        String name = (String) nameField.get(obj);
        System.out.println("通过反射访问私有字段: " + name);
        
        // 调用私有方法
        Method secretMethod = clazz.getDeclaredMethod("secretMethod");
        secretMethod.setAccessible(true); // 设置可访问
        secretMethod.invoke(obj);
    }
    
    // 处理注解
    public static void handleAnnotations() throws Exception {
        Class<?> clazz = AnnotatedClass.class;
        
        // 获取类的方法
        Method[] methods = clazz.getDeclaredMethods();
        
        System.out.println("带注解的方法:");
        for (Method method : methods) {
            // 检查是否有自定义注解
            if (method.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
                System.out.println("方法: " + method.getName());
                System.out.println("  值: " + annotation.value());
                System.out.println("  优先级: " + annotation.priority());
            }
            
            // 检查是否有@Deprecated注解
            if (method.isAnnotationPresent(Deprecated.class)) {
                System.out.println("方法 " + method.getName() + " 已过时");
            }
        }
        
        // 调用带注解的方法
        AnnotatedClass annotatedObj = new AnnotatedClass();
        Method importantMethod = clazz.getMethod("importantMethod");
        Method normalMethod = clazz.getMethod("normalMethod");
        
        // 根据注解优先级排序调用
        if (importantMethod.isAnnotationPresent(MyAnnotation.class) && 
            normalMethod.isAnnotationPresent(MyAnnotation.class)) {
            
            MyAnnotation importantAnnotation = importantMethod.getAnnotation(MyAnnotation.class);
            MyAnnotation normalAnnotation = normalMethod.getAnnotation(MyAnnotation.class);
            
            if (importantAnnotation.priority() > normalAnnotation.priority()) {
                System.out.println("优先调用重要方法:");
                importantMethod.invoke(annotatedObj);
                normalMethod.invoke(annotatedObj);
            } else {
                System.out.println("优先调用普通方法:");
                normalMethod.invoke(annotatedObj);
                importantMethod.invoke(annotatedObj);
            }
        }
    }
}

// 反射的实际应用:通用对象复制工具
class ReflectionUtils {
    // 使用反射复制对象属性
    public static <T> T copyObject(T source, Class<T> targetClass) throws Exception {
        // 创建目标对象实例
        T target = targetClass.newInstance();
        
        // 获取源对象和目标对象的类
        Class<?> sourceClass = source.getClass();
        
        // 获取所有声明的字段
        Field[] fields = sourceClass.getDeclaredFields();
        
        for (Field field : fields) {
            // 设置字段可访问
            field.setAccessible(true);
            
            // 获取字段值
            Object value = field.get(source);
            
            try {
                // 在目标类中查找同名字段
                Field targetField = targetClass.getDeclaredField(field.getName());
                targetField.setAccessible(true);
                targetField.set(target, value);
            } catch (NoSuchFieldException e) {
                // 如果目标类中没有该字段,忽略
                System.out.println("目标类中没有字段: " + field.getName());
            }
        }
        
        return target;
    }
    
    // 使用反射打印对象信息
    public static void printObjectInfo(Object obj) throws Exception {
        if (obj == null) {
            System.out.println("对象为null");
            return;
        }
        
        Class<?> clazz = obj.getClass();
        System.out.println("对象类型: " + clazz.getSimpleName());
        
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object value = field.get(obj);
            System.out.println("  " + field.getName() + " = " + value);
        }
    }
}

// 反射工具使用示例
class ReflectionUtilsExample {
    public static void main(String[] args) {
        try {
            System.out.println("=== 反射工具使用示例 ===");
            
            // 创建原始对象
            Person original = new Person("赵六", 35, "zhaoliu@example.com");
            System.out.println("原始对象:");
            ReflectionUtils.printObjectInfo(original);
            
            // 使用反射复制对象
            Person copy = ReflectionUtils.copyObject(original, Person.class);
            System.out.println("\n复制对象:");
            ReflectionUtils.printObjectInfo(copy);
            
            // 修改复制对象
            copy.setAge(40);
            System.out.println("\n修改复制对象后:");
            System.out.println("原始对象年龄: " + original.getAge());
            System.out.println("复制对象年龄: " + copy.getAge());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过本章节的学习,您已经掌握了Java面向对象编程的高级特性,包括抽象类与接口的使用、静态成员与final关键字的应用、内部类与匿名类的创建,以及反射机制的原理和应用。这些特性是Java编程中非常重要的概念,掌握它们将帮助您编写更加灵活、可维护和功能强大的Java程序。