[Effective Java] Item 22: Favor
Item 22主要讲述了四种nested classes(嵌套类)。Nested classes是在某一个类的内部的类(define a class within another class - from oracle doc),它为了它的enclosing classes/outer classes(外围类)提供服务。具体形式如下:
class OuterClass { // outer class is also enclosing class
// ...
class NestedClass {
// ...
}
}
Nested classes有四种:
- static member class 静态成员类
- nonstatic member class 非静态成员类
- anonymous class 匿名类
- local class 局部类
后三中被称为inner class(内部类)。下面我们一一进行介绍。
Static Member Class
被标注为static的nested class是static member class。
static member class可以access所有enclosing class里面的member,即使这个member被标记为private。
如果想要使用static member class,要通过enclosing class name:OuterClass.StaticNestedClass
。比如:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
private static member classes常见用法是代表enclosing class所代表的对象的组件。
比如说,对于一个Map的实例,它有key和value。很多Map的实现(比如HashMap, TreeMap)对一个个key-value pair有一个内部的Entry。虽然每个Entry都和Map相关,但是作用在Entry上的方法getKey, getValue, setValue都不需要实际access Map。
Nonstatic Member Class
于static member class不同,如果nested class没有被标记为static,那就是nonstatic member class。
如果要创造一个nonstatic member class的实例,必须先创建它的outer class的实例。
nonstatic member class的一种常见用法是定义 adapter,它允许outer class的实例被看做是另一个不相关的类的实例。
Anonymous Classes
匿名类有不少特点和限制:
- 沒有名字
- 不是enclosing class的member
- 除了它们被声明的当下 其他时候它们无法生成实例
- 不能用instanceof
- 不能用一个匿名类实现多个接口
- 不能同时extend a class和implement an interface
第一个常见的用法是用anonymous classes创建function objects。比如下面Collections
的sort
就用了匿名的comparator
。
// Anonymous class instance as a function object
Collections.sort(numbers, new Comparator<String>() {
public int compare(int num1, int num2) {
return Integer.compare(num1*num1, num2*num2);
}
});
第二个常见的用法是用anonymous classes创建process objects。比如Runnable, Thread, TimerTask的实例。
第三个常见的用法是在一个static factory methods里使用。
Local Classes
Local Classes (oracle doc) 是指那些被定义在块中的类,简而言之就是:任何可以声明局部变量的地方都可以声明局部类。它是最少被使用到的nested class。oracle doc里面有实际的例子。
Summary
总的来说四种nested class有各自的使用场景。
- 如果一个nested class需要在一个method外可见,或者因为太长而无法很好的放进一个method里面,可以使用member class (static/nonstatic)。
- 如果nested class的实例需要reference到它外部类的实例,使用nonstatic member class,否则用static member class。
- 假设一个class属于一个method,如果你只需要在一个地方使用,而且事先有定义这个class的类型,你可以使用anonymous class,否则使用local class。
Reference