🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [内部类方法和作用域](https://lingcoder.gitee.io/onjava8/#/book/11-Inner-Classes?id=%e5%86%85%e9%83%a8%e7%b1%bb%e6%96%b9%e6%b3%95%e5%92%8c%e4%bd%9c%e7%94%a8%e5%9f%9f) 到目前为止,读者所看到的只是内部类的典型用途。通常,如果所读、写的代码包含了内部类,那么它们都是“平凡的”内部类,简单并且容易理解。然而,内部类的语法覆盖了大量其他的更加难以理解的技术。例如,可以在一个方法里面或者在任意的作用域内定义内部类。 这么做有两个理由: 1. 如前所示,你实现了某类型的接口,于是可以创建并返回对其的引用。 2. 你要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的。 在后面的例子中,先前的代码将被修改,以用来实现: 1. 一个定义在方法中的类。 2. 一个定义在作用域内的类,此作用域在方法的内部。 3. 一个实现了接口的匿名类。 4. 一个匿名类,它扩展了没有默认构造器的类。 5. 一个匿名类,它执行字段初始化。 6. 一个匿名类,它通过实例初始化实现构造(匿名内部类不可能有构造器)。 第一个例子展示了在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类。这被称作局部内部类: ~~~ // innerclasses/Parcel5.java // Nesting a class within a method public class Parcel5 { public Destination destination(String s) { final class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } @Override public String readLabel() { return label; } } return new PDestination(s); } public static void main(String[] args) { Parcel5 p = new Parcel5(); Destination d = p.destination("Tasmania"); } } ~~~ **PDestination**类是`destination()`方法的一部分,而不是**Parcel5**的一部分。所以,在`destination()`之外不能访问**PDestination**,注意出现在**return**语句中的向上转型-返回的是**Destination**的引用,它是**PDestination**的基类。当然,在`destination()`中定义了内部类**PDestination**,并不意味着一旦`destination()`方法执行完毕,**PDestination**就不可用了。 你可以在同一个子目录下的任意类中对某个内部类使用类标识符**PDestination**,这并不会有命名冲突。 下面的例子展示了如何在任意的作用域内嵌入一个内部类: ~~~ // innerclasses/Parcel6.java // Nesting a class within a scope public class Parcel6 { private void internalTracking(boolean b) { if(b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; } String getSlip() { return id; } } TrackingSlip ts = new TrackingSlip("slip"); String s = ts.getSlip(); } // Can't use it here! Out of scope: //- TrackingSlip ts = new TrackingSlip("x"); } public void track() { internalTracking(true); } public static void main(String[] args) { Parcel6 p = new Parcel6(); p.track(); } } ~~~ **TrackingSlip**类被嵌入在**if**语句的作用域内,这并不是说该类的创建是有条件的,它其实与别的类一起编译过了。然而,在定义**Trackingslip**的作用域之外,它是不可用的,除此之外,它与普通的类一样。