声明和实例化
- 普通类:声明时具有一个名称,并且可以在任何地方多次实例化
class MyRunnable implements Runnable {
public void run() {
// Do something
}
}
// 实例化
Runnable runnable = new MyRunnable();
```
- 匿名类:在声明的同时进行实例化,没有名称,且只能使用一次。通常用于创建接口的实现或者是类的子类的对象。
Runnable runnable = new Runnable() {
public void run() {
// Do something
}
};
```
作用域
- 普通类:可以在它们被定义的整个包内(或更广泛地,如果它们是公共的)重复使用。
- 匿名类:作用域局限于它们被声明的块内。
构造器
- 普通类:可以有一个或多个构造器,并且可以有不同的参数列表。
- 匿名类:没有构造器。匿名类不能定义任何“构造函数”。但可以通过实例初始化块来模拟构造器的效果,也可以使用超类的构造器。
访问局部变量
- 普通类:不能直接访问定义它们的方法的局部变量,除非这些局部变量是
final
的或者是effectively final(即从本质上是final,即使没有被final修饰)。 - 匿名类:同样受到这样的限制,它们可以访问外部方法的final或effectively final的局部变量。
Lambda表达式
- 随着Java 8的引入,许多原本使用匿名类的场景都可以被Lambda表达式所取代,但Lambda表达式只能用于函数式接口的实现。
序列化
- 普通类:如果实现了
Serializable
接口,则可以被序列化。 - 匿名类:即使它们的超类可以被序列化,匿名类通常也不是为了序列化而设计的,因为它们没有稳定的类名称。
可读性和维护性
- 普通类:通常更易于阅读和维护,因为它们有明确的名称和定义。
- 匿名类:可能会使代码难以阅读,尤其是当匿名类很大或者有多个匿名类嵌套时。
使用场景
- 普通类:适用于需要多次实例化,或者具有复杂行为的场景。
- 匿名类:适合于简单的扩展或实现,尤其是当这种行为只需要一次时。
总的来说,匿名类适用于那些仅需要一次使用的实现,而普通类则适用于需要重复使用和可能需要更多逻辑的情况。随着Java 8的Lambda表达式和方法引用,可以以更简洁的方式来替代许多匿名类的使用。