第22条:优先考虑静态成员类

嵌套类指被定义在一个类的内部的类。嵌套类存在的目的应该只是为它的外围类提供服务。如果嵌套类将来可能用于其他环境,它应该是顶层类。

嵌套类有四种:静态成员类,非静态成员类,匿名类,局部类。

静态成员类的常见用法是作为公有的辅助类,仅当与外部类一起使用才有意义,考虑一个枚举,它描述计算器支持的各种操作,Operation枚举应该是Caculator类的公有静态成员类,然后就可以使用如Caculator.Operation.PLUS这样的名称来引用这些操作。

非静态成员类的每个实例都隐含与外围类的一个外围实例相关联,在非静态实例方法内部,可以调用外围实例上的方法,或者利用修饰过的this构造获得外围实例的引用。如果嵌套类的实例可以在它的外围类的实例之外独立存在,这个嵌套类必须是静态成员类,因为在没有外围实例的情况下,要想创建非静态成员类是不可能的。

非静态成员类的常见用法是定义一个Adapter,它允许外部类的实例被看作一个不相关类的实际。例如,Map接口实现往往使用非静态成员类来实现它们的集合视图,这些集合视图由keySet,entrySet和Values方法返回。Set和List的迭代器也用非静态成员类来实现:

public class MySet<E> extends AbstractSet<E> {
    public Iterator<E> iterator() {
        return new MyIterator();
    }
    private class MyIterator implements Iterator<E> {
        ...
    }
}

如果成员类不要求访问外围实例,就要使它称为静态成员类,因为对于非静态成员类,要有指向外围类实例的引用,保存这份引用消耗时间和空间。

私有的静态成员类的一种常用用法是用来代表外围类所代表对象的组件。如一个Map实例,它把键和值关联起来,许多Map实现的内部都有一个Entry对象,对应于Map中的键值对。虽然每个entry都与一个Map关联,但entry上的方法getValue和setValue不需要访问该Map,因此,私有的静态成员类是最佳选择。

如果内部类是导出类的公有的或受保护的成员,在静态和非静态成员类之间做出正确选择非常重要,因为一旦做出选择,在后续的版本就不能修改。

匿名类没有名字,不是外围类的一个成员,在使用的同时被声明和实例化。常见用法是动态地创建函数对象,例如:

Arrays.sort(stringArray, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

另一种常见用法是创建过程对象,如Runnable、Thread或者TimerTask实例,第三种常见用法是在静态工厂方法的内部。

局部类使用的最少,在任何可以声明局部变量的地方,都可以声明局部类,局部类名字,可以被重复利用(在有效范围内)。

总结:如果一个嵌套类需要在单个方法之外仍然可见,或者它太长了,不适合放在方法内部,就应该使用成员类。如果成员类的每个实例都需要一个指向外围实例的引用,就做成非静态的,否则做成静态的。如果这个嵌套类属于一个方法的内部,只需要在一个地方创建实例,并且有预置的类型可以说明这个类的特征,就做成匿名类,否则,做成局部类。

原文地址:https://www.cnblogs.com/13jhzeng/p/5712833.html