优先考虑静态成员类

概述

嵌套类是定义在另一个类中的类,一共有四种嵌套类:静态成员类、非静态成员类、匿名类以及局部类。

静态成员类

静态成员类可以看做是一个普通的类,只是这个类恰好在别的类内部被声明,并且它可以访问外围类的所有成员,即便是私有成员。

静态成员类通用的做法是作为一个公有的辅助类,与它的外围类一起工作。

非静态成员类

语法上来说,静态成员类和非静态成员类之间的区别是,静态成员类在声明上有static标识符。非静态成员类与它的外围类的实例关联,并且可以调用外围实例的方法,或者通过标识了this的构造器来获取外围实例的引用。

在非静态成员类实例被创建时,非静态成员类实例和它的外围实例的关联就被建立了,而且建立后就不能被修改了。

非静态成员类的一个通常的用法是,定义一个适配器:

1
2
3
4
5
6
7
8
9
10
11
// Typical use of a nonstatic member class
public class MySet<E> extends AbstractSet<E> {
... // Bulk of the class omitted
@Override
public Iterator<E> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<E> {
...
}
}

另外,如果你声明了一个不需要访问外围实例的成员类,那你总是应该static修饰符加到声明里去,这是因为非静态成员类每个实例都会包含一个隐含的外围实例的引用,耗费时间和空间。并且,即便外围实例已经可以被回收,但因为这个非静态的成员类实例,外围实例也会被保留。

私有静态成员类通常被用来展示代表外围类对象的组件。

匿名类

匿名类可以没有名字,它并不是外围类的一个成员。它不仅与其它成员一起被声明,而且它在被使用时同时被声明和初始化。其名称由Java编译器给出,一般是形如:外部类名称+$+匿名类顺序

当且仅当匿名类出现在非静态的上下文当中时,匿名类才有外围实例。但即使它们出现在静态的上下文当中,也不能拥有除了常量型变量的任何的静态成员,这些常量型变量是final的基本类型,或者初始化常量表达式的字符串属性。

局部类

在四种嵌套类里,局部类是最不常用的。在可以声明局部变量的地方就可以声明局部类。

总结

  • 如果一个嵌套类必须在方法外部可见,或者放在方法内部会显得太长时,就使用成员类;
  • 如果成员类的实例需要拥有该类的外围类的引用,就将其做成非静态;不然,就将其做成静态;
  • 假设一个类应当在方法内部,若你需要只从一个地方创建实例而且已经存在一个类型能说明这个类的特征,那么将其做成匿名类;否则,就将其做成局部类;