您的位置:首页 > 编程语言 > Java开发

Java的回调函数

2014-09-06 00:00 176 查看
摘要: 借JavaScript的回调函数谈谈Java版的实现

暂且不提回调函数的各种定义,如我本人,虽然知道JavaScript的回调的使用,但是百科了回调的定义,还是觉得云里来雾里去。所以大可先从已熟悉的入手,旁推侧引它的原理,再引出Java版的实现。 因为博主首先只懂得JavaScript版的回调实现,所以开门见山,先看一段关于JavaScript版的实现Demo。

/**
* simple way to access js callback
*
* Created by choaklin on 14-9-6.
*/
;
// define namespace
var jSkill = {};

jSkill.work = function(callback) {
// first, do something about 'work' logical business
var name = 'Nancy';
console.log('i have done my work');

// end, invoke callback function
callback(name);
};

jSkill.reportWork = function(reporter) {
var date = new Date(),
now = date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate();
console.log('Hi, Boss, worker[' + reporter + '] have done her/his works at ' + now);
};

测试入口代码:

<!DOCTYPE html>
<html>
<body>
<script src="../script/callback.js"></script>
<script>
window.onload = function() {
jSkill.work(jSkill.reportWork);
};
</script>
</body>
</html>
运行结果:



代码分析:

首先定义了一个namespace—jSkill,避免污染了全局对象。其次在jSkill下定义了功能函数work,你可以想象成它是为响应一个业务而生的。它接收一个参数,是一个预想的函数对象,并且函数内部完成逻辑业务后也把它当作函数使用(函数名() 这是JS调用函数的语法)。接着又声明了个函数reportWork,顾名思义汇报工作用,一个纯粹的函数。 最后界面调用的时候,把reportWork函数当作参数传递给work。页面一加载完,于是就有了如上图的运行结果。

进一步的挖掘,发现JS的回调函数的主要组成因素有:

主调用方得持有被调用方的引用,即函数work运行完自己的主逻辑想打个回马枪,调用reportWork,那么就得持有reportWork的句柄(引用)

在JavaScript中,一切皆是对象,所以函数也是对象,所以也可以当作参数被互相传递

JS部分的回调函数暂时告一段落,接下来我们拿着从JS总结的“回调的组成因素”来看看Java这边的实现

jSkill.work——Worker类

package callback.simple;

/**
* created by choaklin on 14-9-5.
*/
public class Worker {

private String name;

public Worker(String name) {
this.name = name;
}

public void work(Report report) {
// first, do something about 'work' logical business
System.out.println("i have done my work ");

// end, invoke callback function
report.report(name);
}
}

jSkill.reportWork——Report接口及WorkReport类

public interface Report {

public void report(String reporter);
}

public class WorkReport implements Report {

@Override
public void report(String name) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
String now = dateFormat.format(calendar.getTime());

System.out.println("Hi, Boss, worker[" + name + "] have done her/his works at " + now);
}
}
测试入口——ReportMain类

public class ReportMain {

public static void main(String[] args) {
Worker worker = new Worker("Nancy");
WorkReport workReport = new WorkReport();

worker.work(workReport);
}
}
运行结果:



代码分析: 略

相比于JS的弱类型及运行时语言、一切皆是对象等特性,使得声明一个函数参数可以指向各种不同的函数实现。而对于Java不行,首先函数不是一个对象;其次它是安全性的语言,不允许存在模凌两可的情况出现。也许有人说,更简洁的代码就是直接在Worker#work声明参数为WorkReport类型。OK,程序是可以运行的,结果也是一致的,但是达不到与JS等价的效果——jSkill.work#callback是可以指向任何函数,可Worker#work将只能一直使用WorkReport类型。如果哪天需求改成HealthyReport,显然代码要改2处:客户端调用及参数声明处,不显然利于代码的维护。最好的解决方案就是使用接口。所以在Java中,接口编程实现了回调,回调传播了接口编程。

最后再来看下网上几个关于回调函数的定义,我已经若有所得,你呢?

计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码引用

程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法

......

这一次的探索,让我不仅懂了回调在Java的实现,更重要的打开了Java中重要的接口编程的大门。

注:Java版的实现并非实际应用的最佳实践,仅供学习使用:-)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JS回调 Java回调