求java接口java中回调函数详解。

Java 利用接口实现回调
在 Java 支持方法指针之前,Java 接口不能提供一种实现回调的好方法。如果您习惯于传递在事件驱动编程模型中调用的函数指针,则您会喜欢本技巧。
熟悉 MS-Windows 和 X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即&回调&)的函数指针。Java 的面向对象模型目前并不支持方法指针,这样似乎就不可能使用这种很好的机制。但我们并不是一点办法都没有!
Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明我们要调用的方法。
例如,假定我们希望在某个事件发生时得到通知。我们可以定义一个接口:
[java]& public interface InterestingEvent{&&
// 这仅是一个常规方法。因此如果需要,&&&
// 它可有返回值,也可接收参数。&&&
public void interestingEvent ();&&
public interface InterestingEvent{
// 这仅是一个常规方法。因此如果需要,
// 它可有返回值,也可接收参数。
public void interestingEvent ();
这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。与在将 C++ 代码用于 Motif 时使用窗口小部件的数据域来容纳对象指针的难以控制的 C 函数相比,这种方法要好得多。
发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent() 方法。
[java]& public class EventNotifier{&&
private InterestingE&&
private boolean somethingH&&
public EventNotifier (InterestingEvent event){&&
// 保存事件对象以备后用。&&&
// 还没有要报告的事件。&&&
somethingHappened =&&
public void doWork (){&&
// 检查在别处设置的谓词。&&&
if (somethingHappened){&&
// 通过调用接口的这个方法发出事件信号。&&&
ie.interestingEvent ();&&
public class EventNotifier{
private InterestingE
private boolean somethingH
public EventNotifier (InterestingEvent event){
// 保存事件对象以备后用。
// 还没有要报告的事件。
somethingHappened =
public void doWork (){
// 检查在别处设置的谓词。
if (somethingHappened){
// 通过调用接口的这个方法发出事件信号。
ie.interestingEvent ();
在上例中,我使用 somethingHappened 谓词来跟踪是否应触发事件。在许多情况下,调用此方法足以保证向 interestingEvent() 发出信号。
希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。
[java]& &SPAN style=&FONT-SIZE: 18px&&&STRONG&public class CallMe implements InterestingEvent{&&
private EventN&&
public CallMe (){&&
// 创建事件通知程序,并将自身引用传递给它。&&&
en = new EventNotifier (this);&&
// 为事件定义实际的处理程序。&&&
public void interestingEvent (){&&
// 噢!必定发生了感兴趣的事件!&&&
// 执行某些操作 ...&&&
&/STRONG&&/SPAN&&
public class CallMe implements InterestingEvent{
private EventN
public CallMe (){
// 创建事件通知程序,并将自身引用传递给它。
en = new EventNotifier (this);
// 为事件定义实际的处理程序。
public void interestingEvent (){
// 噢!必定发生了感兴趣的事件!
// 执行某些操作 ...
下面给出上述例子的完整实现:
[java] /*&
&* 考虑这样一个应用:希望在某个事件发生时得到通知&
interface InterestingEvent {&&&
&&& public void interestingEvent();&&&
class EventNotifier {&&&
&&& private InterestingE&&&&&&& //写成private List&InterestingEvent& eventList可以监听多个事件&&&&
&&& private boolean somethingH&&&
&&& public EventNotifier(InterestingEvent ie) {&&&
&&&&&&& this.ie =&&&
&&&&&&& this.somethingHappened =&&&
&&& public void setHappened() {&&&
&&&&&&& this.somethingHappened =&&&
&&& public void doWork() {&&&
&&&&&&& if (somethingHappened) {&&&
&&&&&&&&&&& ie.interestingEvent();&&&
&&&&&&& }&&&
class ButtonPressedEvent implements InterestingEvent {&&&
&&& @SuppressWarnings(&unused&)&&&
&&& private EventN&&&
&&& public ButtonPressedEvent() {&&&
&&&&&&& en = new EventNotifier(this);&&&
&&& public void interestingEvent() {&&&
&&&&&&& System.out.println(&button pressed &);&&&
class EventNotifierTest {&&&
&&& public static void test() {&&&
&&&&&&& //这里有两种调用方法。其中第二种采用匿名内部类,其原理跟上面&改变Client名字&是一样的&&&&
&&&&&&& EventNotifier en = new EventNotifier(new ButtonPressedEvent());&&&
&&&&&&& en.setHappened();&&&
&&&&&&& en.doWork();&&&
&&&&&&&&&&&
&&&&&&& EventNotifier en2 = new EventNotifier(new InterestingEvent(){&&&
&&&&&&&&&&& public void interestingEvent() {&&&
&&&&&&&&&&&&&&& System.out.println(&inputtext change &);&&&
&&&&&&&&&&& }&&&
&&&&&&& });&&&
&&&&&&& en2.setHappened();&&&
&&&&&&& en2.doWork();&&&
&&&&&&&&&&&
//这个类是用来测试的&&&&
public class JavaInterfaceCallBack {&&&
&&& public static void main(String[] args) {&&&
&&&&&&&&&&
&&&&&&& ChangeNameTest.test();&&&
&&&&&&& EventNotifierTest.test();&&&
&&&&&&&&&&&
&* 考虑这样一个应用:希望在某个事件发生时得到通知
interface InterestingEvent {&
&&& public void interestingEvent();&
class EventNotifier {&
&&& private InterestingE&&&&&&& //写成private List&InterestingEvent& eventList可以监听多个事件&
&&& private boolean somethingH&
&&& public EventNotifier(InterestingEvent ie) {&
&&&&&&& this.ie =&
&&&&&&& this.somethingHappened =&
&&& public void setHappened() {&
&&&&&&& this.somethingHappened =&
&&& public void doWork() {&
&&&&&&& if (somethingHappened) {&
&&&&&&&&&&& ie.interestingEvent();&
&&&&&&& }&
class ButtonPressedEvent implements InterestingEvent {&
&&& @SuppressWarnings(&unused&)&
&&& private EventN&
&&& public ButtonPressedEvent() {&
&&&&&&& en = new EventNotifier(this);&
&&& public void interestingEvent() {&
&&&&&&& System.out.println(&button pressed &);&
class EventNotifierTest {&
&&& public static void test() {&
&&&&&&& //这里有两种调用方法。其中第二种采用匿名内部类,其原理跟上面&改变Client名字&是一样的&
&&&&&&& EventNotifier en = new EventNotifier(new ButtonPressedEvent());&
&&&&&&& en.setHappened();&
&&&&&&& en.doWork();&
&&&&&&& EventNotifier en2 = new EventNotifier(new InterestingEvent(){&
&&&&&&&&&&& public void interestingEvent() {&
&&&&&&&&&&&&&&& System.out.println(&inputtext change &);&
&&&&&&&&&&& }&
&&&&&&& });&
&&&&&&& en2.setHappened();&
&&&&&&& en2.doWork();&
//这个类是用来测试的&
public class JavaInterfaceCallBack {&
&&& public static void main(String[] args) {&
&&&&&&& ChangeNameTest.test();&
&&&&&&& EventNotifierTest.test();&
下面给出回调的模型和另一个实例以便我们更好的学习
[java] /*&
&* Java里面的接口回调,最简单的情况示意如下&
interface A {}&&&
class B implements A {}&&&
class C implements A {}&&&
class Test {&&&
&&& A b = new B();&&&
&&& A c = new C();&&&
&* Java里面的接口回调,最简单的情况示意如下
interface A {}&
class B implements A {}&
class C implements A {}&
class Test {&
&&& A b = new B();&
&&& A c = new C();&
[java] view plaincopyprint?/*&
&* 考虑这样一个应用: NameChanger动态地改变Client的名字&
&* 那NameChanger的changeName方法就要接收一个Client对象,然后获取(调用)Client的名字并作不同的处理&
&* Client也要持有NameChanger,因为要打印改变后的名字&
class Client {&&&
&&& private INameC&&&
&&& private String clientN&&&
&&& public Client(INameChanger changer) {&&&
&&&&&&& this.changer =&&&
&&& public void showMyNewName() {&&&
&&&&&&& String newName = changer.changeName(Client.this);&&&
&&&&&&& System.out.println(newName);&&&
&&& public String getName() {&&&
&&&&&&& return clientN&&&
&&& public void setName(String clientName) {&&&
&&&&&&& this.clientName = clientN&&&
&interface INameChanger {&&&
&&& public String changeName(Client client);&&&
public class ChangeNameTest {&&&
&&& public static void main(String[] args) {&&&
&&&&&&&&&&&
&&&&&&& Client client = new Client(new INameChanger(){&&&
&&&&&&&&&&& public String changeName(Client client) {&&&
&&&&&&&&&&&&&&& return &Mr.& + client.getName();&&&
&&&&&&&&&&& }&&&
&&&&&&& });&&&
&&&&&&& client.setName(&Tom&);&&&
&&&&&&& client.showMyNewName();&&&
&&&&&&&&&&&
&&&&&&& Client client2 = new Client(new INameChanger(){&&&
&&&&&&&&&&& public String changeName(Client client) {&&&
&&&&&&&&&&&&&&& return &Miss.& + client.getName();&&&
&&&&&&&&&&& }&&&
&&&&&&& });&&&
&&&&&&& client2.setName(&Lucy&);&&&
&&&&&&& client2.showMyNewName();&&&
&&&&&&&&&&&
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'JAVA回调机制(CallBack)详解 - ImportNew
最近学习java,接触到了回调机制(CallBack)。初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义。当然了,我在理解了回调之后,再去看网上的各种讲解,确实没什么问题。但是,对于初学的我来说,缺了一个循序渐进的过程。此处,将我对回调机制的个人理解,按照由浅到深的顺序描述一下,如有不妥之处,望不吝赐教!
开始之前,先想象一个场景:幼稚园的小朋友刚刚学习了10以内的加法。
第1章. 故事的缘起
幼师在黑板上写一个式子 “1 + 1 = ”,由小明同学来填空。
由于已经学习了10以内的加法,小明同学可以完全靠自己来计算这个题目,模拟该过程的代码如下:
public class Student
private String name =
public Student(String name)
// TODO Auto-generated constructor stub
this.name =
public void setName(String name)
this.name =
private int calcADD(int a, int b)
return a +
public void fillBlank(int a, int b)
int result = calcADD(a, b);
System.out.println(name + &心算:& + a + & + & + b + & = & + result);
小明同学在填空(fillBalnk)的时候,直接心算(clacADD)了一下,得出结果是2,并将结果写在空格里。测试代码如下:
public class Test
public static void main(String[] args)
int a = 1;
int b = 1;
Student s = new Student(&小明&);
s.fillBlank(a, b);
运行结果如下:
小明心算:1 + 1 = 2
该过程完全由Student类的实例对象单独完成,并未涉及回调机制。
第2章. 幼师的找茬
课间,幼师突发奇想在黑板上写了“168 + 291 = ”让小明完成,然后回办公室了。
花擦!为什么所有老师都跟小明过不去啊?明明超纲了好不好!这时候小明同学明显不能再像上面那样靠心算来完成了,正在懵逼的时候,班上的小红同学递过来一个只能计算加法的计算器(奸商啊)!!!!而小明同学恰好知道怎么用计算器,于是通过计算器计算得到结果并完成了填空。
计算器的代码为:
public class Calculator
public int add(int a, int b)
return a +
修改Student类,添加使用计算器的方法:
public class Student
private String name =
public Student(String name)
// TODO Auto-generated constructor stub
this.name =
public void setName(String name)
this.name =
@SuppressWarnings(&unused&)
private int calcADD(int a, int b)
return a +
private int useCalculator(int a, int b)
return new Calculator().add(a, b);
public void fillBlank(int a, int b)
int result = useCalculator(a, b);
System.out.println(name + &使用计算器:& + a + & + & + b + & = & + result);
测试代码如下:
public class Test
public static void main(String[] args)
int a = 168;
int b = 291;
Student s = new Student(&小明&);
s.fillBlank(a, b);
运行结果如下:
小明使用计算器:168 + 291 = 459
该过程中仍未涉及到回调机制,但是部分小明的部分工作已经实现了转移,由计算器来协助实现。
3. 幼师回来了
发现小明完成了3位数的加法,老师觉得小明很聪明,是个可塑之才。于是又在黑板上写下了“26549 + 16487 = ”,让小明上课之前完成填空,然后又回办公室了。
小明看着教室外面撒欢儿的小伙伴,不禁悲从中来。再不出去玩,这个课间就要废了啊!!!! 看着小红再一次递上来的计算器,小明心生一计:让小红代劳。
小明告诉小红题目是“26549 + 16487 = ”,然后指出填写结果的具体位置,然后就出去快乐的玩耍了。
这里,不把小红单独实现出来,而是把这个只能算加法的计算器和小红看成一个整体,一个会算结果还会填空的超级计算器。这个超级计算器需要传的参数是两个加数和要填空的位置,而这些内容需要小明提前告知,也就是小明要把自己的一部分方法暴漏给小红,最简单的方法就是把自己的引用和两个加数一块告诉小红。
因此,超级计算器的add方法应该包含两个操作数和小明自身的引用,代码如下:
public class SuperCalculator
public void add(int a, int b, Student
int result = a +
xiaoming.fillBlank(a, b, result);
小明这边现在已经不需要心算,也不需要使用计算器了,因此只需要有一个方法可以向小红寻求帮助就行了,代码如下:
public class Student
private String name =
public Student(String name)
// TODO Auto-generated constructor stub
this.name =
public void setName(String name)
this.name =
public void callHelp (int a, int b)
new SuperCalculator().add(a, b, this);
public void fillBlank(int a, int b, int result)
System.out.println(name + &求助小红计算:& + a + & + & + b + & = & + result);
测试代码如下:
public class Test
public static void main(String[] args)
int a = 26549;
int b = 16487;
Student s = new Student(&小明&);
s.callHelp(a, b);
运行结果为:
小明求助小红计算:26549 + 16487 = 43036
执行流程为:小明通过自身的callHelp方法调用了小红(new SuperCalculator())的add方法,在调用的时候将自身的引用(this)当做参数一并传入,小红在使用计算器得出结果之后,回调了小明的fillBlank方法,将结果填在了黑板上的空格里。
灯灯灯!到这里,回调功能就正式登场了,小明的fillBlank方法就是我们常说的回调函数。
通过这种方式,可以很明显的看出,对于完成老师的填空题这个任务上,小明已经不需要等待到加法做完且结果填写在黑板上才能去跟小伙伴们撒欢了,填空这个工作由超级计算器小红来做了。回调的优势已经开始体现了。
第4章. 门口的婆婆
幼稚园的门口有一个头发花白的老婆婆,每天风雨无阻在那里摆着地摊卖一些快过期的垃圾食品。由于年纪大了,脑子有些糊涂,经常算不清楚自己挣了多少钱。有一天,她无意间听到了小明跟小伙伴们吹嘘自己如何在小红的帮助下与幼师斗智斗勇。于是,婆婆决定找到小红牌超级计算器来做自己的小帮手,并提供一包卫龙辣条作为报酬。小红经不住诱惑,答应了。
回看一下上一章的代码,我们发现小红牌超级计算器的add方法需要的参数是两个整型变量和一个Student对象,但是老婆婆她不是学生,是个小商贩啊,这里肯定要做修改。这种情况下,我们很自然的会想到继承和多态。如果让小明这个学生和老婆婆这个小商贩从一个父类进行继承,那么我们只需要给小红牌超级计算器传入一个父类的引用就可以啦。
不过,实际使用中,考虑到java的单继承,以及不希望把自身太多东西暴漏给别人,这里使用从接口继承的方式配合内部类来做。
换句话说,小红希望以后继续向班里的小朋友们提供计算服务,同时还能向老婆婆提供算账服务,甚至以后能够拓展其他人的业务,于是她向所有的顾客约定了一个办法,用于统一的处理,也就是自己需要的操作数和做完计算之后应该怎么做。这个统一的方法,小红做成了一个接口,提供给了大家,代码如下:
public interface doJob
public void fillBlank(int a, int b, int result);
因为灵感来自帮小明填空,因此小红保留了初心,把所有业务都当做填空(fillBlank)来做。
同时,小红修改了自己的计算器,使其可以同时处理不同的实现了doJob接口的人,代码如下:
public class SuperCalculator
public void add(int a, int b, doJob
int result = a +
customer.fillBlank(a, b, result);
小明和老婆婆拿到这个接口之后,只要实现了这个接口,就相当于按照统一的模式告诉小红得到结果之后的处理办法,按照之前说的使用内部类来做,代码如下:
public class Student
private String name =
public Student(String name)
// TODO Auto-generated constructor stub
this.name =
public void setName(String name)
this.name =
public class doHomeWork implements doJob
public void fillBlank(int a, int b, int result)
// TODO Auto-generated method stub
System.out.println(name + &求助小红计算:& + a + & + & + b + & = & + result);
public void callHelp (int a, int b)
new SuperCalculator().add(a, b, new doHomeWork());
老婆婆的:
public class Seller
private String name =
public Seller(String name)
// TODO Auto-generated constructor stub
this.name =
public void setName(String name)
this.name =
public class doHomeWork implements doJob
public void fillBlank(int a, int b, int result)
// TODO Auto-generated method stub
System.out.println(name + &求助小红算账:& + a + & + & + b + & = & + result + &元&);
public void callHelp (int a, int b)
new SuperCalculator().add(a, b, new doHomeWork());
测试程序如下:
public class Test
public static void main(String[] args)
int a = 56;
int b = 31;
int c = 26497;
int d = 11256;
Student s1 = new Student(&小明&);
Seller s2 = new Seller(&老婆婆&);
s1.callHelp(a, b);
s2.callHelp(c, d);
运行结果如下:
小明求助小红计算:56 + 31 = 87
老婆婆求助小红算账:26497 + 11256 = 37753元
可以很明显的看到,小红已经把这件事情当做一个事业来做了,看她给接口命的名字doJob就知道了。
有人也许会问,为什么老婆婆摆摊能挣那么多钱? 你的关注点有问题好吗!!这里聊的是回调机制啊!!
我只知道,后来小红的业务不断扩大,终于在幼稚园毕业之前,用挣到的钱买了人生的第一套房子。
可能感兴趣的文章
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
– 好的话题、有启发的回复、值得信赖的圈子
– 写了文章?看干货?去头条!
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 活跃 & 专业的翻译小组
– 国内外的精选博客文章
– UI,网页,交互和用户体验
– JavaScript, HTML5, CSS
– 专注Android技术分享
– 专注iOS技术分享
– 专注Java技术分享
– 专注Python技术分享
& 2016 ImportNewThinking in Java之接口回调
&&&& 回调概念
&&&&&&& &回调,回调&到底是个啥呢?
&&&&&&&&&&&&& 通过以前的学习知道的是在事件驱动设计模式情况下,回调就是将一个方法的指针传递给事件源
&&&&&&&& 当某一事件发生的时候就调用该方法,这个过程就称为回调,调用的方法就称为回调方法了。
&&&&&&&&&&&&& 不过我们知道的是java面向对象的程序设计并不支持方法指针,似乎难以实现?不过仔细想想就
&&&&&&&&& 可以其实就可以知道java可以使用接口这一技术来实现相同的回调嘛。&&&
&&&& 接口回调&
&&&&&&&&&&&&&& java中接口回调其实现技巧就是定义一个简单的接口,并在接口中声明我们需要调用的方法。当某
&&&&&&&& 一事件发生的时候我们就通过实现这个接口的方法进行回调,接口的这个方法也就是回调方法了。
&&&&&&&& 只是说明很难让人理解,看看具体如何去实现吧!
&&&&& 接口回调简单实现
&&&&&&&&&&&&&&& 其实这在前一篇关于&匿名内部类&的思考中java接口回调就有使用过。
&&&&&&&&&&&&&&& 首先编写一个接口,并声明一些需要回调的方法&&
package com.&
/**@author Kiritor
&* 事件接口*/&
interface& EventListener {&
&& void clicked();&
&& void pressed();&
&& /*其他的就不多写了*/&
package com.
/**@author Kiritor
&* 事件接口*/
interface& EventListener {
&& void clicked();
&& void pressed();
&& /*其他的就不多写了*/
&&&&&&&&&&&&&&&&& 这里有时候接口的方法过多的话在使用内部类实现调用的时候会存在不便,因此编写一个
&&&&&&&&&& Adapter进行&适配&。
package com.&
&* @author Kiritor 事件监听的适配器
public class EventAdapter implements EventListener {&
&&& @Override&
&&& public void clicked() {&
&&&&&&& // TODO Auto-generated method stub&&
&&& public void pressed() {&
package com.
&* @author Kiritor 事件监听的适配器
public class EventAdapter implements EventListener {
&&& @Override
&&& public void clicked() {
&&&&&&& // TODO Auto-generated method stub
&&& public void pressed() {
&&&&&&&&& 编写一个按钮类,它有添加监听的方法,也就是对按钮的状态改变的进行监听
&&&&& 并执行相关的动作!
package com.&
&* @author Kiritor 一个按钮
public class MyButton {&
&&& private int flag = 0;// 0代表点击,1代表按下&&
&&& public MyButton(int flag) {&
&&&&&&& this.flag =&
&&& //对按钮添加监听&&
&&& public void addListener(EventListener eventListener) {&
&&&&&&& if (flag == 0) {&
&&&&&&&&&&& eventListener.clicked();&
&&&&&&& } else&
&&&&&&&&&&& eventListener.pressed();&
package com.
&* @author Kiritor 一个按钮
public class MyButton {
&&& private int flag = 0;// 0代表点击,1代表按下
&&& public MyButton(int flag) {
&&&&&&& this.flag =
&&& //对按钮添加监听
&&& public void addListener(EventListener eventListener) {
&&&&&&& if (flag == 0) {
&&&&&&&&&&& eventListener.clicked();
&&&&&&& } else
&&&&&&&&&&& eventListener.pressed();
}&&&&&&&&& 看一看测试类:
package com.&
public class Test {&
&&& public static void main(String[] args) {&
&&&&&&& MyButton button = new MyButton(1);&
&&&&&&&&&&&&&&&& //对按钮添加监听,采用的是Adapter的模式&&
&&&&&&&&&&&&&&& button.addListener(new EventAdapter() {&
&&&&&&&&&&& @Override&
&&&&&&&&&&& public void clicked() {&
&&&&&&&&&&&&&&& // TODO Auto-generated method stub&&
&&&&&&&&&&&&&&& System.out.println(&按钮被点击了&);&
&&&&&&&&&&& }&
&&&&&&&&&&& @Override&
&&&&&&&&&&& public void pressed() {&
&&&&&&&&&&&&&&& // TODO Auto-generated method stub&&
&&&&&&&&&&&&&&& System.out.println(&按钮被按下了&);&
&&&&&&&&&&& }&
&&&&&&& });&
package com.
public class Test {
&public static void main(String[] args) {
&&MyButton button = new MyButton(1);
&&&&&&&&&&&&&&&& //对按钮添加监听,采用的是Adapter的模式
&&&&&&&&&&&&&&& button.addListener(new EventAdapter() {
&&&@Override
&&&public void clicked() {
&&&&// TODO Auto-generated method stub
&&&&System.out.println(&按钮被点击了&);
&&&@Override
&&&public void pressed() {
&&&&// TODO Auto-generated method stub
&&&&System.out.println(&按钮被按下了&);
&&&&&&&&&&&&& 上述代码基本上实现了java中awt的相同功能,只是说按钮状态的监听是人为的,因为
&&&& 按钮状态的改变时底层才知道的。
&&&&&&&&&&&&&& 仔细阅读上述代码部分,我们来看看java中是怎么通过接口进行回调的!
&&&&&&&&&&&&&&& 首先看看EventListener接口,不用多说那一定是定义了需要回调的方法。
&&&&&&&&&&& 其次是EventAdapter这个实现了EventListener,在这里没有太过苛刻的要求,读者也可以
&&&&& 不实现它。(其实这算一种设计模式,就不多说了)
&&&&&&&&&&& 接下来就是按钮了MyButton,这里面主要的是方法
&PRE class=java name=&code&&//对按钮添加监听&&
&&& public void addListener(EventListener eventListener) {&
&&&&&&& if (flag == 0) {&
&&&&&&&&&&& eventListener.clicked();&
&&&&&&& } else&
&&&&&&&&&&& eventListener.pressed();&
&&& }&/PRE&&
&PRE&&/PRE&&
&PRE&&/PRE&&
&P&&&&&&& 这里要结合测试类来看,如下&/P&&
&PRE class=java name=&code&&&&&&&&&&&& button.addListener(new EventAdapter() {&
&&&&&&&&&&& @Override&
&&&&&&&&&&& public void clicked() {&
&&&&&&&&&&&&&&& // TODO Auto-generated method stub&&
&&&&&&&&&&&&&&& System.out.println(&按钮被点击了&);&
&&&&&&&&&&& }&
&&&&&&&&&&& @Override&
&&&&&&&&&&& public void pressed() {&
&&&&&&&&&&&&&&& // TODO Auto-generated method stub&&
&&&&&&&&&&&&&&& System.out.println(&按钮被按下了&);&
&&&&&&&&&&& }&
&&&&&&& });&/PRE&&
&P&&&&&&&&&&&&&&& &BR&&
&P&&&&&&&&&&& new 出来一个按钮并对其添加监听,形成一个匿名内部类对象传递给EventListener接口&/P&&
&P&&&&&& 由其&SPAN style=&COLOR: #990000&&回调&/SPAN&相应的接口方法。该匿名内部类可以有选择的实现需要的方法,这也是为什么&/P&&
&P&&&&&& 不直接使用EventListener接口的原因。我们知道java中是动态绑定的,最后调用的方法,也&/P&&
&P&&&&&& 就是匿名内部类中重新实现的方法。&/P&&
&P&&&&&&&&&&& 因此结果输出为:&SPAN style=&COLOR: #990000&&按钮被按下了&/SPAN&&/P&&
&H2&&A name=t4&&/A&&&&&&&& 重新理解回调&/H2&&
&P&&&&&&&&&&&&&&&&&&&& 通过创建匿名类,动态实现了接口的回调方法,侧重点在于接口,虽说使用的是&/P&&
&P&&&&&&&&&& EventAdapter但是阅读器源码可以知道,我们并未对其做太多的事情,他只是一种&辅助&&/P&&
&P&&&&&&&&&& 手段!我们真正在意的是重新实现的方法,&SPAN style=&COLOR: #ff0000&&这个方法是提供个外部实现并由接口回调的&/SPAN&。&/P&&
&P&&&&&&&&&&&&&&& &SPAN style=&COLOR: #663300&&&& 通俗的来讲就是:我提供给你一个接口的方法交给Coder实现,coder实现过后却由接口&/SPAN&&/P&&
&P&&SPAN style=&COLOR: #663300&&&&&&&&&& 进行回调。&/SPAN&& Coder并不能就行直接调用。&/P&&
&PRE&&/PRE&&
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 java中回调函数 的文章

 

随机推荐