内部类允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。 内部类看起来像一种代码隐藏机制;同时它了解外围类,并能与之通信。 Private(成员)内部类: 可以完全阻止任何依赖于类型的编码?? (将内部类向上转型为基类或者接口,通过方法返回的只是指向基类或接口的引用,就像new了一个接口对象)(这时扩展接口没有价值) (甚至无法实现向下转型,因为无法访问该类名) 完全隐藏了实现的细节(private修饰) 嵌套类: static修饰的(成员)内部类 内部类对象与其外围类对象没有联系(没有保存外部类对象的引用,要创建嵌套类对象并不需要其外部类对象) 不能从嵌套类的对象中访问非静态的外围类成员 普通内部类中不能有static成员(也不能有嵌套类);嵌套类可以包含所有这些东西 局部内部类 定义在方法中(甚至只存在于方法的一个作用域内) 匿名(局部)内部类:(类的定义和创建对象一举完成) 可以继承有非默认构造方法的类(一样传参) 不可能有构造器,可以在类内添加字段初始化(或者构造代码块)来替代 字段初始化所需要的值作为所在方法的参数传入,该形参要声明为final?? 局限是不能重载这种“构造器” 可以扩展类或实现接口,但不能两者兼备 为什么需要内部类 内部类使得多重继承的解决方案变得完整(接口解决了部分问题) 每个内部类都能独立的继承类(实现接口) 通过内部类可以继承多个非接口类型 内部类还有的其他特性: 内部类可以有多个实例,每个实例都有自己独立的状态信息 在单个外部类中,可以让多个内部类以不同方式实现同一个接口(继承同一个类) 内部类并没有令人迷惑的“is - a”关系(当外部类不满足某个is - a测试,但需要继承那个类,可以让内部类继承) 这些特性本身是相当直观的,但这些特性的使用是设计阶段考虑的问题。 当见到这些语言特性的实际应用时,就最终理解它们了。 Tip: 典型的情况是,外部类有一个方法,返回一个指向内部类对象的引用。 如果想从外部类的非静态方法之外的任意位置创建某个内部类对象,必须指明完整类型:外部类.内部类 能访问其外围对象的所有成员,就像他们自己拥有似的 因为,当某个外围类对象创建了一个内部类对象时,内部类对象必定会秘密地捕捉一个指向那个外围类对象的引用,所以在拥有外部类对象之前是不可能创建内部类对象的 内部类(非static时)对象只能在于其外部类对象相关联的情况下才能被创建 所以创建内部类对象时,必须在new表达式中提供对其外部类对象的引用(使用.new语法),同时给外部类对象一个消息,创建其内部类对象的消息,像命令它调用自己的成员方法一样。 如果要在内部类里获得对外部类对象的引用:使用外部类名.this 这个this是外部类的一个隐式成员 只写this获得的是指向内部类对象的引用 *接口内部的类 自动的是public static的 通过这样,可以创建某些公共代码,使得它们可以被某个接口的所有不同实现所公用?? public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { public void howdy() { System.out.println("Howdy!"); } public static void main(String[] args) { new Test().howdy(); } } } /* Output: Howdy! *///:~ 使用嵌套类来放置测试代码(main方法,方便得测试每个类) 会生成一个独立的类TestBed$Tester.class(执行java TestBed$Tester 可以测试) 发布产品时,将这个class文件删除(相当于源码中 类里面没写测试的内部类) public class TestBed { public void f() { System.out.println("f()"); } public static class Tester { public static void main(String[] args) { TestBed t = new TestBed(); t.f(); } } } /* Output: f() *///:~ *多层嵌套类 可以透明得访问它所嵌入的外部类的所有成员 创建多层嵌套的内部类对象的标准写法:.new能产生正确的作用域,所以不必在调用构造器时写完整类名 class MNA { private void f() {} class A { private void g() {} public class B { void h() { g(); f(); } } } } public class MultiNestingAccess { public static void main(String[] args) { MNA mna = new MNA(); MNA.A mnaa = mna.new A(); MNA.A.B mnaab = mnaa.new B(); mnaab.h(); } } ///:~ 闭包与回调 闭包(closure)是一个对象。它记录了一些信息,这些信息来自于创建它的作用域。 内部类对象自动包含外部类对象的引用,可以自由使用外部类的信息,是一个闭包。 通过内部类提供闭包(内部类对象),来实现回调(callback),比指针更灵活、安全。 本例中也能看出interface是如何允许接口与接口的实现完全独立的(private内部类实现接口;public方法提供闭包,即接口引用) interface Incrementable { void increment(); } //接口和类中有相同的方法,所以下面的Callee2使用的内部类来实现多重继承 class MyIncrement { public void increment() { System.out.println("Other operation"); } } // If your class must implement increment() in // some other way, you must use an inner class: class Callee2 extends MyIncrement {//被调用类 private int i = 0; public void increment() { super.increment(); i++; System.out.println(i); } //该内部类对象就是一个闭包(包含了外部类对象的信息) private class Closure implements Incrementable { public void increment() { //这个this是指向Callee2对象(被回调)的引用 //由此提供了闭包的“钩子”(hook)功能 //该闭包只能调用increment方法,是个安全的钩子 Callee2.this.increment(); } } Incrementable getCallbackReference() { //返回闭包 //是一个接口引用 //也是一个回调引用 return new Closure(); } } class Caller { private Incrementable callbackReference; Caller(Incrementable cbh) { callbackReference = cbh; } void go() { callbackReference.increment(); } } public class Callbacks { public static void main(String[] args) { Callee2 c2 = new Callee2(); Caller caller2 = new Caller(c2.getCallbackReference()); caller2.go();//使用闭包回调 caller2.go(); } } *内部类的继承 子类和被继承的内部类一样,其构造方法必须连接到指向其外围类对象的引用?? 所以在继承内部类时:外围类引用必须被初始化;导出类中不再存在可连接的默认对象(所以下例中的wi.super()不能省略)?? class WithInner { class Inner {} } public class InheritInner extends WithInner.Inner {//注意这里被继承的内部类的全名 //! InheritInner() {} // Won't compile InheritInner(WithInner wi) {//注意这里子类构造器的写法 wi.super(); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } } ///:~ *内部类可以被重写吗 如下例所示,导出类和基类中同名的两个内部类是完全独立的两个实体,各自在自己的命名空间内??,互不影响,没有“重写” (继承后父类空间存在于子类空间中。父类的内部类的作用域是父类空间,父类可以使用,但如果是开放权限的内部类,子类也能使用)?? // An inner class cannot be overriden like a method. // 内部类不能像父类方法一样被重写 import static net.mindview.util.Print.*; class Egg { private Yolk y; protected class Yolk { public Yolk() { print("Egg.Yolk()"); } } public Egg() { print("New Egg()"); y = new Yolk(); } } public class BigEgg extends Egg { public class Yolk { public Yolk() { print("BigEgg.Yolk()"); } } public static void main(String[] args) { new BigEgg(); } } /* Output: New Egg() Egg.Yolk() *///:~ 明确继承内部类是可以的: // Proper inheritance of an inner class. import static net.mindview.util.Print.*; class Egg2 { protected class Yolk { public Yolk() { print("Egg2.Yolk()"); } public void f() { print("Egg2.Yolk.f()");} } private Yolk y = new Yolk(); public Egg2() { print("New Egg2()"); } public void insertYolk(Yolk yy) { y = yy; } public void g() { y.f(); } } public class BigEgg2 extends Egg2 { public class Yolk extends Egg2.Yolk { public Yolk() { print("BigEgg2.Yolk()"); } public void f() { print("BigEgg2.Yolk.f()"); } } public BigEgg2() { insertYolk(new Yolk()); } public static void main(String[] args) { Egg2 e2 = new BigEgg2(); e2.g(); } } /* Output:(创建一个子类对象前先创建其父类对象,同样适用于内部类继承的情况) Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f() *///:~ |