迄今为止内部类看起来仍然没什么特别的地方毕竟用它实现隐藏显得有些大题小做Java已经有一个非常优秀的隐藏机制——只允许类成为友好的(只在一个包内可见)而不是把它创建成一个内部类 然而当我们准备上溯造型到一个基础类(特别是到一个接口)的时候内部类就开始发挥其关键作用(从用于实现的对象生成一个接口句柄具有与上溯造型至一个基础类相同的效果)这是由于内部类随后可完全进入不可见或不可用状态——对任何人都将如此所以我们可以非常方便地隐藏实施细节我们得到的全部回报就是一个基础类或者接口的句柄而且甚至有可能不知道准确的类型就象下面这样 //: Parceljava // Returning a handle to an inner class package cparcel; abstract class Contents { abstract public int value(); } interface Destination { String readLabel(); } public class Parcel { private class PContents extends Contents { private int i = ; public int value() { return i; } } protected class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } public Destination dest(String s) { return new PDestination(s); } public Contents cont() { return new PContents(); } } class Test { public static void main(String[] args) { Parcel p = new Parcel(); Contents c = nt(); Destination d = pdest(Tanzania); // Illegal cant access private class: //! ParcelPContents c = pnew PContents(); } } ///:~ 现在Contents和Destination代表可由客户程序员使用的接口(记住接口会将自己的所有成员都变成public属性)为方便起见它们置于单独一个文件里但原始的Contents和Destination在它们自己的文件中是相互public的 在Parcel中一些新东西已经加入内部类PContents被设为private所以除了Parcel之外其他任何东西都不能访问它PDestination被设为protected所以除了ParcelParcel包内的类(因为protected也为包赋予了访问权也就是说protected也是友好的)以及Parcel的继承者之外其他任何东西都不能访问PDestination这意味着客户程序员对这些成员的认识与访问将会受到限制事实上我们甚至不能下溯造型到一个private内部类(或者一个protected内部类除非自己本身便是一个继承者)因为我们不能访问名字就象在classTest里看到的那样所以利用private内部类类设计人员可完全禁止其他人依赖类型编码并可将具体的实施细节完全隐藏起来除此以外从客户程序员的角度来看一个接口的范围没有意义的因为他们不能访问不属于公共接口类的任何额外方法这样一来Java编译器也有机会生成效率更高的代码 普通(非内部)类不可设为private或protected——只允许public或者友好的 注意Contents不必成为一个抽象类在这儿也可以使用一个普通类但这种设计最典型的起点依然是一个接口 |