第十章:内部类(下)

来源:互联网 发布:java 正则表达式 负数 编辑:程序博客网 时间:2024/06/05 09:45

10.8 为什么需要内部类

每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对内部类没有影响。内部类提供可以继承多个具体的或抽象的类的能力。

10.8.1 闭包与回调

闭包(closure)是一个可调用的对象,它记录了一些信息,这些信息来源于创建它的作用域。内部类是面向对象的闭包。
大家自己欣赏一下代码:

// 接口interface Incrementable {    void increment();}// 外部类实现接口class Callee1 implements Incrementable {    private int i = 0;    public void increment() {        i++;        System.out.println(i);    }}// 类class MyIncrement {    public void increment() {        System.out.println("Other operation");    }    static void f(MyIncrement mi) {        mi.increment();    }}// 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() {            // Specify outer-class method, otherwise you'd get an infinite recursion:            Callee2.this.increment();        }    }    // 返回实现了Incrementable类的对象    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) {        Callee1 c1 = new Callee1();        Callee2 c2 = new Callee2();        MyIncrement.f(c2);        Caller caller1 = new Caller(c1);        Caller caller2 = new Caller(c2.getCallbackReference());        caller1.go();        caller1.go();        caller2.go();        caller2.go();    }}

10.8.2 内部类与控制框架

设计模式总是将变化的事物与不变的事物分离开来。

10.9 内部类的继承

class WithInner {    private int i;    class Inner {        public Inner() {            System.out.println("我是内部类构造函数!");        }    }}public class InheritInner extends WithInner.Inner {    public InheritInner(WithInner withInner) {        // 必须加上这句话否则编译错误        withInner.super();    }    public static void main(String[] args) {        WithInner wi = new WithInner();        InheritInner ii = new InheritInner(wi);    }}

内部类持有外部类的引用。在继承内部类的时候,那个指向外部类对象的“秘密的”引用必须被初始化。所以必须在子类的构造器使用如下语法:

enclosingClassReference.super();

这样才提供了必要的引用,程序才可以编译通过。

10.10 内部类可以被覆盖吗

答案当然是不可以,覆盖只是针对于方法而言的。

10.11 局部内部类

局部内部类不能有访问说明符,因为他不是外部类的一部分;但是他可以访问当前代码块内的常量,以及此外部类的所有成员。

interface Counter {    int next();}public class LocalInnerClass {    private int count = 0;    Counter getCounter(final String name) {        // 局部内部类        class LocalCounter implements Counter {            public LocalCounter() {                // Local inner class can have a constructor                System.out.println("LocalCounter()");            }            public int next() {                System.out.println(name); // Access local final                return count++;            }        }        return new LocalCounter();    }    // The same thing with an anonymous inner class:    // 返回匿名内部类    Counter getCounter2(final String name) {        return new Counter() {            // Anonymous inner class cannot have a named            // constructor, only an instance initializer:            {                System.out.println("Counter()");            }            public int next() {                System.out.println(name); // Access local final                return count++;            }        };    }    public static void main(String[] args) {        LocalInnerClass lic = new LocalInnerClass();        Counter c1 = lic.getCounter("Local inner "),                c2 = lic.getCounter2("Anonymous inner ");        for (int i = 0; i < 5; i++)            System.out.println(c1.next());        for (int i = 0; i < 5; i++)            System.out.println(c2.next());    }}

既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是:我们需要一个已经命名的构造器,或者需要重载构造器,而匿名内部类只能用于实例的初始化,所以使用局部内部类而不使用匿名内部类的另一个理由是,需要不止一个内部类对象。局部内部类更灵活。

10.12 内部类标识符

每个类都会生成 .class 文件,那么内部类的 .class 文件叫什么名字呢?
普通内部类:外部类的名称$内部类的名称.class
匿名内部类:外部类的名称$数字.class【使用数字作为其标识符】
如果是多个内部类嵌套:外部类的名称$内部类的名称$内部类的名称… .class

每个内部类都会单独生成一个 .class 文件

0 0