我前一篇博客开始,内部类似乎还只是一种名字隐藏和组织代码的模式。这是是很有用,但还不是最引人注目的,它还有其它的用途。当生成一个内部类的对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何特殊的操作。此外,内部类还拥有其外围类的所有元素的访问权。
interface Selector{
boolean end();
Object current();
void next();
}
public class Sequence {
private Object[] items;
private int next = 0;
private Sequence(int size){items = new Object[size];}
public void add(Object x){
items[next++] = x;
}
private class SequenceSelector implements Selector{
private int i = 0;
@Override
public boolean end() {
return i == items.length;
}
@Override
public Object current() {
return items[i];
}
@Override
public void next() {
if (i < items.length) i++;
}
}
public Selector selector(){
return new SequenceSelector();
}
public static void main(String[] args) {
Sequence sequence = new Sequence(10);
for (int i = 0; i < 10 ; i++)
sequence.add(Integer.toString(i));
Selector selector = sequence.selector();
while (!selector.end()){
System.out.println(selector.current());
selector.next();
}
}
}
Sequence类只是一个固定大小的Object的数组,以类的形式包装了起来。可以调用add()在序列末增加新的Object(只要还有空间)。要获取Sequence中的每一个对象,可以使用Selector接口。这是“迭代器”设计模式的一个例子。Selector允许你检查序列是否已经到了末尾了(end()),访问当前对象(current()),以及移到序列的下一个对象(next())。因为Selector是一个接口,所以别的可以按它们自己的方式来实现这个接口,并且别的方法能以此接口为参数,来生成更加通用的代码。
所有内部类自动拥有对其外围类所有成员的访问权,这是如何做到的呢?当某个外围类的对象创建了一个内部类对象时,此内部类对象必会秘密地捕获一个指向那个外围类的对象的引用。然后,在你访问此外围类的成员时,就是那个引用来选择外围类的成员。幸运的是,编译器会帮你处理所有的细节,但是你现在可以看到,内部类的对象只能在与其外围类的对象相关联的情况下才能被创建(就像你看到的那样,内部类是非static类时)。构造内部类对象是,需要一个指向其外围类对象的引用,如果编译器访问不到这个引用就会报错。不过绝大多数时候都无需程序员操心。