🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [内部类与向上转型](https://lingcoder.gitee.io/onjava8/#/book/11-Inner-Classes?id=%e5%86%85%e9%83%a8%e7%b1%bb%e4%b8%8e%e5%90%91%e4%b8%8a%e8%bd%ac%e5%9e%8b) 当将内部类向上转型为其基类,尤其是转型为一个接口的时候,内部类就有了用武之地。(从实现了某个接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上效果是一样的。)这是因为此内部类-某个接口的实现-能够完全不可见,并且不可用。所得到的只是指向基类或接口的引用,所以能够很方便地隐藏实现细节。 我们可以创建前一个示例的接口: ~~~ // innerclasses/Destination.java public interface Destination { String readLabel(); } ~~~ ~~~ // innerclasses/Contents.java public interface Contents { int value(); } ~~~ 现在**Contents**和**Destination**表示客户端程序员可用的接口。记住,接口的所有成员自动被设置为**public**。 当取得了一个指向基类或接口的引用时,甚至可能无法找出它确切的类型,看下面的例子: ~~~ // innerclasses/TestParcel.java class Parcel4 { private class PContents implements Contents { private int i = 11; @Override public int value() { return i; } } protected final class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } @Override public String readLabel() { return label; } } public Destination destination(String s) { return new PDestination(s); } public Contents contents() { return new PContents(); } } public class TestParcel { public static void main(String[] args) { Parcel4 p = new Parcel4(); Contents c = p.contents(); Destination d = p.destination("Tasmania"); // Illegal -- can't access private class: //- Parcel4.PContents pc = p.new PContents(); } } ~~~ 在**Parcel4**中,内部类**PContents**是**private**,所以除了**Parcel4**,没有人能访问它。普通(非内部)类的访问权限不能被设为**private**或者**protected**;他们只能设置为**public**或**package**访问权限。 **PDestination**是**protected**,所以只有**Parcel4**及其子类、还有与**Parcel4**同一个包中的类(因为**protected**也给予了包访问权)能访问**PDestination**,其他类都不能访问**PDestination**,这意味着,如果客户端程序员想了解或访问这些成员,那是要受到限制的。实际上,甚至不能向下转型成**private**内部类(或**protected**内部类,除非是继承自它的子类),因为不能访问其名字,就像在**TestParcel**类中看到的那样。 **private**内部类给类的设计者提供了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并且完全隐藏了实现的细节。此外,从客户端程序员的角度来看,由于不能访问任何新增加的、原本不属于公共接口的方法,所以扩展接口是没有价值的。这也给 Java 编译器提供了生成高效代码的机会。