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()。