JAVA_闭包

之前总结了下匿名内部类,想到了js的闭包,那么java有没有闭包相关的动作呢?
回去翻了翻《JAVA编程思想》发现有闭包和回调的相关说明,但书中的说法不是很好理解,因为有些兴趣,仿照着书中代码做个例子看看。稍微研究下。代码如下:

// 增加计数功能定义
// 注意,接口只存在一个void increment(),所以所有实现它的对象中,
// 只存在public的void increment,其他的成员都是private
interface Incremental {
    void increment();
}
// 调用者:保存计数功能对象,并调用
class Caller{
    private Incremental callbackReference;
    Caller(Incremental incrementable){callbackReference = incrementable;}
    void go(){callbackReference.increment();}
}
// 实现class1:简单的实现增加计数
class Callee1 implements Incremental {
    private int num = 0;
    @Override
    public void increment() {
        System.out.println("Callee1:增加计数功能实现"+(++num));
    }
}
// 实现class2:在实现功能的同时实现回调
class Callee2 extends Callback implements Incremental {
    private int num = 0;
    @Override
    public void increment(){
        System.out.println("Callee2:增加计数功能实现"+(++num));
        super.increment();
    }
    // 闭包,内部类Closure调用了外部变量num
    private class Closure implements Incremental {
        @Override
        public void increment() {
            System.out.println("Callee2-Closure:增加计数功能实现"+(++num));
            Callee2.super.increment();
        }
    }
    public Incremental getCallbackReference(){
        return  new Closure();
    }
}
// 回调用类
class Callback {
    public void increment(){System.out.println("回调内容执行...");}
    static void fun(Callback myIncrement){myIncrement.increment();}
}

public class test_closure {
    // 执行部分
    public static void main(String[] arge){
        // 简单的实现,使用调用者调用
        Caller caller1 = new Caller(new Callee1());
        caller1.go();
        caller1.go();
        // 结果:
        // Callee1:增加计数功能实现1
        // Callee1:增加计数功能实现2

        // 追加回调方法的实现
        // 回调对象执行实现对象
        Callee2 callee2 = new Callee2();
        Callback.fun(callee2);
        // 结果:
        // Callee2:增加计数功能实现1
        // 回调内容执行...

        // 使用调用者调用
        Caller caller2 = new Caller(callee2.getCallbackReference());
        caller2.go();
        caller2.go();
        // 结果:
        // Callee2-Closure:增加计数功能实现2
        // 回调内容执行...
        // Callee2-Closure:增加计数功能实现3
        // 回调内容执行...
    }
}

以上是经过理解并追加注释的结果,书上的代码例子,不敲下来实在太难理解了……
注意是Callee1只是对比用,没回调和闭包,Callee2中存在内部类,内部类调用了Callee2的私有变量num——闭包;Callee2的getCallbackReference方法返回内部类,而内部类中,实现了接口的同时,调用了回调类的内容——回调。
……说实话,不知道是思维方式还是理解能力的问题,觉得这个例子实在很麻烦。还是自己弄个例子吧。


闭包

那么,首先是闭包。说道闭包,还是js比较多,那么,这里随便写个例子。

function Incrementable(){
  var num = 0;
  return function(){  // 这里,类似java直接返回内部类
    num = num+1;
	console.log(num)
  }
}
var Callee = Incrementable();
Callee();
Callee();
console.log(num);

// 执行结果:
1
2
Uncaught ReferenceError: i is not defined

这个例子其实和之前java的闭包例子是一样,同样是自增的实现,内部变量num在Incrementable之外无法访问,但是Incrementable内的function内部可以访问。
将以上的例子转成java的话是这样的:

// 自增长接口和实现类
interface Incrementable{
    void increment();
}
class Callee {
    private int num = 0;
    public Incrementable getIncrementable(){
        return new Incrementable(){
            @Override
            public void increment() {
                System.out.println("Callee:增加计数功能实现"+(++num));
            }
        };
    }
}
public class test_closure2 {
    // 执行部分
    public static void main(String[] arge){
        Callee callee = new Callee();
        callee.getIncrementable().increment();
        callee.getIncrementable().increment();
        callee.getIncrementable().increment();
        // 结果:
        // Callee:增加计数功能实现1
        // Callee:增加计数功能实现2
        // Callee:增加计数功能实现3
    }
}

可以看到,java类似js一样的,对内部的num变量实现了改变。一般工作中可能不这么写,但是翻翻源码,如此定义的方式还是很多的。原因在于这是一种不改变原本结构进行更新的方法,也可以根据结构的变化,切换功能,需要注意。

posted @ 2018-04-17 14:20  常烦常乐  阅读(202)  评论(0编辑  收藏  举报