• Java 中,匿名内部类 是一种没有名字的类,通常用于简化代码。它用于实现接口或继承类的实例化,通常是在需要创建一次性对象的场景下使用。


    1. 什么是匿名内部类?

    匿名内部类 是在声明和实例化类的同时完成的,它没有类名。它可以:

    • 继承一个类
    • 实现一个接口

    语法:

    1
    2
    3
    new 父类或接口(参数) {
    // 重写方法或定义新方法
    }

    2. 使用场景和示例

    场景一:继承类的匿名内部类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Animal {
    void sound() {
    System.out.println("动物发出声音");
    }
    }

    public class Main {
    public static void main(String[] args) {
    // 创建匿名内部类继承 Animal
    Animal cat = new Animal() {
    @Override
    void sound() {
    System.out.println("喵喵叫");
    }
    };

    cat.sound(); // 输出:喵喵叫
    }
    }

    解释:

    • 使用 new Animal() 创建一个继承 Animal 的匿名类,并重写了 sound() 方法。
    • 这种写法适合需要临时重写父类方法的场景。

    场景二:实现接口的匿名内部类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    interface Greeting {
    void sayHello();
    }

    public class Main {
    public static void main(String[] args) {
    // 使用匿名内部类实现接口
    Greeting greeting = new Greeting() {
    @Override
    public void sayHello() {
    System.out.println("你好,Java!");
    }
    };

    greeting.sayHello(); // 输出:你好,Java!
    }
    }

    解释:

    • 匿名类实现了 Greeting 接口并重写了 sayHello() 方法。
    • 适合需要一次性实现接口的场景。

    场景三:结合线程的匿名内部类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Main {
    public static void main(String[] args) {
    // 使用匿名内部类创建线程
    Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
    System.out.println("线程正在运行: " + Thread.currentThread().getName());
    }
    });

    thread.start();
    }
    }

    解释:

    • 匿名类实现了 Runnable 接口,并直接传递给 Thread
    • 适合简单的多线程场景。

    场景四:使用 Lambda 替代匿名内部类

    对于只有一个抽象方法的接口(即函数式接口),Java 8 引入了 Lambda 表达式,可以更简洁地替代匿名内部类。

    示例:使用 Lambda 替代匿名内部类

    1
    2
    Greeting greeting = () -> System.out.println("你好,Lambda!");
    greeting.sayHello();

    解释:

    • Lambda 只能用于函数式接口。
    • 使用 -> 符号简化代码。

    3. 匿名内部类的特点

    • 没有类名,只能通过父类或接口的引用进行操作。
    • 一次性使用,通常用于简化代码。
    • 可以直接重写方法,无需额外创建类文件。
    • 不能有构造方法,但可以使用实例代码块进行初始化。

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Person {
    Person(String name) {
    System.out.println("Person 构造方法: " + name);
    }
    }

    public class Main {
    public static void main(String[] args) {
    // 使用实例代码块代替构造方法
    Person person = new Person("张三") {
    {
    System.out.println("匿名内部类中的初始化块");
    }
    };
    }
    }

    输出:

    1
    2
    Person 构造方法: 张三
    匿名内部类中的初始化块

    4. 总结:什么时候使用匿名内部类?

    • 临时性需求:只需要一次性实现接口或重写方法。
    • 简化代码:不需要创建额外的类文件。
    • 事件监听器:在 GUI 程序中广泛使用匿名内部类处理事件。
    • 线程创建:快速实现 Runnable