匿名内部类
「我只想在这里用一次这个接口的实现,还要单独写一个类?」
匿名内部类就是来解决这个问题的——没有名字,用完即弃。
基本语法
java
public class AnonymousBasicDemo {
interface Greeting {
void sayHello();
}
public static void main(String[] args) {
// 匿名内部类:直接 new 接口 + 实现
Greeting greeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("Hello!");
}
};
greeting.sayHello();
}
}实现接口 vs 继承抽象类
实现接口
java
abstract class Animal {
abstract void makeSound();
}
public class AnonymousExtendDemo {
public static void main(String[] args) {
// 匿名内部类继承抽象类
Animal dog = new Animal() {
@Override
void makeSound() {
System.out.println("Woof!");
}
};
dog.makeSound();
}
}带构造参数
匿名内部类没有名字,怎么传构造参数?答案是通过实例初始化块:
java
public class AnonymousWithInitDemo {
static abstract class Config {
abstract String getValue();
}
public static void main(String[] args) {
Config config = new Config() {
private String name = "my-config";
private int timeout = 30;
{
// 实例初始化块,可以做初始化逻辑
System.out.println("Config initialized");
}
@Override
public String getValue() {
return name + ":" + timeout;
}
};
System.out.println(config.getValue());
}
}Lambda 简化(JDK 8+)
如果是函数式接口(只有一个抽象方法的接口),可以用 Lambda 进一步简化:
java
public class LambdaComparison {
interface Calculator {
int calculate(int a, int b);
}
public static void main(String[] args) {
// 匿名内部类
Calculator add1 = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda 表达式
Calculator add2 = (a, b) -> a + b;
// Lambda + 方法引用
Calculator add3 = Integer::sum;
System.out.println(add1.calculate(1, 2)); // 3
System.out.println(add2.calculate(1, 2)); // 3
System.out.println(add3.calculate(1, 2)); // 3
}
}实际应用场景
线程创建
java
public class ThreadAnonymousDemo {
public static void main(String[] args) {
// 匿名内部类
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread running");
}
});
// Lambda 简化
Thread t2 = new Thread(() -> System.out.println("Thread running"));
t1.start();
t2.start();
}
}集合排序
java
import java.util.*;
public class SortAnonymousDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("Java", "Python", "Go", "Rust");
// 匿名内部类
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s2.length() - s1.length();
}
});
// Lambda 简化
list.sort((s1, s2) -> s2.length() - s1.length());
// Comparator 组合
list.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(list);
}
}注意事项
- 没有名字:匿名内部类没有类名,不能有构造方法
- 一次性:每个匿名内部类都是独立的类,只创建一个实例
- 简化条件:必须是函数式接口才能用 Lambda 替代
- 调试困难:匿名内部类的堆栈跟踪不够直观
- 适度使用:如果逻辑复杂或需要复用,还是应该用命名类
