关于Java回调函数

做Android开发,很长一段时间都不明白回调函数是什么意思,每天对着类似button.setOnClickListener这样的语句,感到很莫名其妙。
后来看了看网上各种大牛的解释,也算是明白了。

在这里,我想抛开概念性的东西,主要写一下自己的理解。

为了能把这东西说明白,我们结合一下情景:

1.假设我们有一个库,类似开发安卓应用时候的SDK,在一个名叫“test.library”的package里。

2.假设我们的程序main函数在我们自己的“test.callbacktest” package里。

3.我们要做什么呢?很简单:程序运行时候new一部手机,然后调用手机的开机函数。手机呢,是在库里提供的。


因此大概的目录结构就是这样的:

test.callbacktest

    TestMain.java

test.library

    CellPhone.java


代码也很简单,首先是库里提供的CellPhone类,他仅有一个代表开机的函数turnOnPhone():

package test.library;

public class CellPhone {
	
	public void turnOnPhone() {
		System.out.println("开机...");
		System.out.println("电源键在左侧");
	}

}

然后是我们的main函数:

package test.callbacktest;

import test.library.CellPhone;

public class TestMain {
	
	public static void main(String[] args) {
		CellPhone phone = new CellPhone();
		phone.turnOnPhone();
	}

}

这程序运行的输出再简单不过了:

开机...
电源键在左侧


那么现在问题来了:

手机得开机键不一定在左侧啊,有的在上面,有的在下面。可能有人说:“你在CellPhone类里面设置个代表电源键位置的属性得了,开机时候读取一下属性值。”但现在这不是为了说明回调函数么,牵强一下吧,咱们在这用回调函数的方式给它实现了。

都说Java里的回调函数用interface实现,这里也这么设计。我们的目标是:在开机时候,我们能自己控制显示开机键在哪边,但我们不去手动打印出来,而是让CellPhone自己打印出来。

那首先给这个接口起个名字,用惯了onClickListener,onTouchListener,这手机开机的回调函数接口就叫OnTurnOnPhoneListener得了:

package test.library;

public interface OnTurnOnPhoneListener {
	
	public void onTurnOnPhone();

}

这接口里面只有一个函数onTurnOnPhone()。

回调么,就是我们想在手机开机时调用这函数,并且是CellPhone这个类自己调用,不是我们手动调用:

1.那调用的那行代码自然要写在CellPhone这个类里面了,写在turnOnPhone()这个函数里。

2.接口要去实现,那么自然就有了实现了这个接口的对象。

所以——让CellPhone类里面有这么一个实现了OnTurnOnPhoneListener接口的对象,就能调用这个对象里的方法了。

这流程就是这样:

1.CellPhone的开机方法里面,调用开机回调函数的这个接口——里面的函数。

2.而我们自己实现这个接口,并把它传递给CellPhone,这样CellPhone开机时候就能调用我们实现的函数了。

怎么传?setOnTurnOnPhoneListener呗,在CellPhone类里面添加这么个方法,和实现接口的对象:

package test.library;

public class CellPhone {
	
	OnTurnOnPhoneListener onTurnOnPhoneListener = null;    //实现回调函数接口的对象
	
	//在main函数中,通过这个方法,把我们实现的回调函数设置进来
	public void setTurnOnPhoneListener(OnTurnOnPhoneListener listener) {
		onTurnOnPhoneListener = listener;
	}
	
	public void turnOnPhone() {
		System.out.println("开机...");
		if(onTurnOnPhoneListener != null) {
			onTurnOnPhoneListener.onTurnOnPhone();    //调用我们实现的回调函数
		}
	}

}

注意在调用回调函数的地方,首先判断是不是为空。然后在我们的main函数里添加一句调用phone.setOnTurnOnPhoneListener的语句。参数里的接口实现对象,可以写一个类去实现接口,这里为了简便,直接用内部类了:

package test.callbacktest;

import test.library.CellPhone;
import test.library.OnTurnOnPhoneListener;

public class TestMain {
	
	public static void main(String[] args) {
		CellPhone phone = new CellPhone();
		
		//设置回调函数
		phone.setTurnOnPhoneListener(new OnTurnOnPhoneListener() {
			@Override
			public void onTurnOnPhone() {
				System.out.println("电源键在上侧");
			}
		});
		
		phone.turnOnPhone();
	}

}

运行一下,很理想:

开机...
电源键在上侧


当然如果我们不设置那个匿名的实现类,就只会打印“开机...”那一行了。这就像不为button设置onClickListener,只会有按钮点击的效果一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值