Java编程思想的两个代码
参考:On Java8 中文版
1. 闭包与回调
// innerclasses/Callbacks.java
// Using inner classes for callbacks
// {java innerclasses.Callbacks}
package innerclasses;
interface Incrementable {
void increment();
}
// Very simple to just implement the interface:
class Callee1 implements Incrementable {
private int i = 0;
@Override
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;
@Override
public void increment() {
super.increment();
i++;
System.out.println(i);
}
private class Closure implements Incrementable {
@Override
public void increment() {
// Specify outer-class method, otherwise
// you'll get an infinite recursion:
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) {
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();
}
}
输出
Other operation
1
1
2
Other operation
2
Other operation
3
-
创建
Callee1的实例c1,它的i为0。 -
创建
Callee2的实例c2,它的i为0。 -
执行
MyIncrement.f(),因为传入的是c2,执行c2.increment()。
先执行super.increament(),所以打印Other Operation
然后执行i++,所以c2的i为1
最后打印1 -
创建
Caller的实例caller1,它的callbackReference是c1。 -
创建
Caller的实例caller2,它的callbackReference是new Closure()。 -
执行
caller1.go(),再执行c1.increment(),c1的i自增1,i为1,打印1 -
执行
caller1.go(),再执行c1.increment(),c1的i自增1,i为2,打印2 -
执行
caller2.go(),再执行c2的Closure的increment(),然后执行c2.increment()
打印Other Operation
打印2 -
执行
caller2.go(),再执行c2的Closure的increment(),然后执行c2.increment()
打印Other Operation
打印3
2. 内部类可以被覆盖吗?
// innerclasses/BigEgg2.java
// Proper inheritance of an inner class
class Egg2 {
protected class Yolk {
public Yolk() {
System.out.println("Egg2.Yolk()");
}
public void f() {
System.out.println("Egg2.Yolk.f()");
}
}
private Yolk y = new Yolk();
Egg2() { System.out.println("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() {
System.out.println("BigEgg2.Yolk()");
}
@Override
public void f() {
System.out.println("BigEgg2.Yolk.f()");
}
}
public BigEgg2() { insertYolk(new Yolk()); }
public static void main(String[] args) {
Egg2 e2 = new BigEgg2();
e2.g();
}
}
输出
Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk.f()
-
执行
main(),在new BigEgg2()的时候先创建Egg2。
因为Egg2有一个赋了值的private成员,所以先执行Egg2.Yolk(),打印Egg2.Yolk()。
然后回到Egg2(),打印New Egg2()。
最后回到BigEgg2(),执行insertYolk()。 -
因为
insertYolk()是在Egg2里的,所以它接收的参数Yolk yy也是Egg2.Yolk类型。
但是BigEgg2调用insertYolk的时候传过去的new Yolk()是BigEgg2.Yolk,继承了Egg2.Yolk,所以是向上转型。
因此,先调用Egg2.Yolk(),打印Egg2.Yolk()。
再调用BigEgg2.Yolk(),打印BigEgg2.Yolk()。 -
执行
e2.g()。因为BigEgg2.Yolk已经重写了f(),而且e2去new的时候是new BigEgg2()。
所以不会调用Egg2.f(),而是调用BigEgg2.Yolk.f()。
这个也叫协变返回类型,打印BigEgg2.Yolk.f()。

本文深入探讨Java中闭包与回调的概念,通过具体代码示例解释内部类如何用于实现回调机制。同时,分析了内部类的继承特性,展示了内部类在不同上下文中如何被重写和使用。

被折叠的 条评论
为什么被折叠?



