第十章:内部类(下)

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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

outer199

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值