java内部类的例子:链接到外部类
迄今为止,我们见到的内部类好象仅仅是一种名字埋没以及代码组织方案。尽量这些成果很是有用,但好像并不出格引人注目。然而,我们还忽略了另一个重要的事实。建设本身的内部类时,谁人类的工具同时拥有指向封装工具(这些工具封装或生成了内部类)的一个链接。所以它们能会见谁人封装工具的成员——毋需取得任何资格。除此以外,内部类拥有对封装类所有元素的会见权限(注释②)。下面这个例子阐示了这个问题:
//: Sequence.java // Holds a sequence of Objects interface Selector { boolean end(); Object current(); void next(); } public class Sequence { private Object[] o; private int next = 0; public Sequence(int size) { o = new Object[size]; } public void add(Object x) { if(next < o.length) { o[next] = x; next++; } } private class SSelector implements Selector { int i = 0; public boolean end() { return i == o.length; } public Object current() { return o[i]; } public void next() { if(i < o.length) i++; } } public Selector getSelector() { return new SSelector(); } public static void main(String[] args) { Sequence s = new Sequence(10); for(int i = 0; i < 10; i++) s.add(Integer.toString(i)); Selector sl = s.getSelector(); while(!sl.end()) { System.out.println((String)sl.current()); sl.next(); } } } ///:~
②:这与C++“嵌套类”的设计颇有差异,后者只是一种纯真的名字埋没机制。在C++中,没有指向一个封装工具的链接,也不存在默认的会见权限。
个中,Sequence只是一个巨细牢靠的工具数组,有一个类将其封装在内部。我们挪用add(),以便将一个新工具添加到Sequence末端(假如尚有处所的话)。为了取得Sequence中的每一个工具,要利用一个名为Selector的接口,它使我们可以或许知道本身是否位于最末端(end()),能寓目当前工具(current() Object),以及可以或许移至Sequence内的下一个工具(next() Object)。由于Selector是一个接口,所以其他很多类都能用它们本身的方法实现接口,并且很多要领都能将接口作为一个自变量利用,从而建设一般的代码。
在这里,SSelector是一个私有类,它提供了Selector成果。在main()中,各人可看到Sequence的建设进程,在它后头是一系列字串工具的添加。随后,通过对getSelector()的一个挪用生成一个Selector。并用它在Sequence中移动,同时选择每一个项目。
从外貌看,SSelector好像只是另一个内部类。但不要被外貌现象疑惑。请留意调查end(),current()以及next(),它们每个要领都引用了o。o是个不属于SSelector一部门的句柄,而是位于封装类里的一个private字段。然而,内部类可以从封装类会见要领与字段,就象已经拥有了它们一样。这一特征对我们来说长短常利便的,就象在上面的例子中看到的那样。
因此,我们此刻知道一个内部类可以会见封装类的成员。这是如何实现的呢?内部类必需拥有对封装类的特定工具的一个引用,而封装类的浸染就是建设这个内部类。随后,当我们引用封装类的一个成员时,就操作谁人(埋没)的引用来选择谁人成员。幸运的是,编译器会辅佐我们照管所有这些细节。但我们此刻也可以领略内部类的一个工具只能与封装类的一个工具连系建设。在这个建设进程中,要求对封装类工具的句柄举办初始化。若不能会见谁人句柄,编译器就会报错。举办所有这些操纵的时候,大大都时候都不要求措施员的任何参与。