Java中callback作为函数参数传递

java 专栏收录该内容
4 篇文章 0 订阅

反射方法类Method

需要callback函数为变量时,java通常用反射(java.lang.reflect)的相关方法。

import java.lang.reflect.Method;

利用Method类和invoke方法实现传递callback

例如
以TestAClass.AddProduce(int a, int b)是需要回调的函数,为了体现函数作为参数可变的优势,这里写2个回调函数:

public class TestAClass {
	ArrayList<Integer> list = new ArrayList<>();
	public void AddProduct(int a, int b) {
		list.add(a * b);
	}
	public void AddSum(int a, int b) {
		list.add(a + b);
	}
}

TestBClass.testCall()是被调函数:

public class TestBClass {
	public void testCall(Method func) throws Exception {
		TestAClass aobj = new TestAClass();
		for (int i = 0; i < 10; i++)
			func.invoke(aobj, i, i + 1);
	}
}

执行invoke时第一个参数需要执行的对象。在上面代码中是新建了一个AClass对象,这样的话会导致对象的类还是在方法中被严格限制。

虽然这里可能可以用func.getDeclaringClass()来获取目标类型,但是我们仍然有可能希望限制执行回调函数的对象。

因此当我们希望执行回调的对象也是特定变量时,就需要改为:

public class TestBClass {
	public void testCall(object obj, Method func) throws Exception {
		for (int i = 0; i < 10; i++)
			func.invoke(obj, i, i + 1);
	}
}

调用这个函数时:

		TestAClass tcb = new TestAClass();
		TestBClass tc = new TestBClass();
		Method callback = new Method(tcb.getClass().getMethod("AddProduct", int.class, int.class));
		tc.testCall(tcb, callback);
		for (int i : tcb.list) {
			System.out.println(i);
		}
		tcb.list.clear();
		System.out.println("-------");
		callback = new Method(tcb.getClass().getMethod("AddSum", int.class, int.class));
		tc.testCall(tcb, callback);
		for (int i : tcb.list) {
			System.out.println(i);
		}

至此就可以完成传递回调函数作为变量。

封装CallBack类

每当我们需要把一个函数的回调函数改为变参时,我们就需要同时在调用函数的参数和invoke上加上obj、method这2个参数,当频繁添加回调时感觉很麻烦。因此考虑重新封装一个CallBack类,简化回调的参数。
如下:

public class CallBack {
	Object ownobj;
	Method execute;
	public CallBack(Object o, Method method) {
		ownobj = o;
		execute = method;
	}
	public Object invoke(Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		return execute.invoke(ownobj, args);
	}
}

回调函数无变化:

public class TestAClass {
	ArrayList<Integer> list = new ArrayList<>();
	public void AddProduct(int a, int b) {
		list.add(a * b);
	}
	public void AddSum(int a, int b) {
		list.add(a + b);
	}
}

调用函数简化为:

public class TestBClass {
	public void testCall(CallBack func) throws Exception {
		for (int i = 0; i < 10; i++)
			func.invoke(i, i + 1);
	}
}

调用改为:

		TestAClass tcb = new TestAClass();
		TestBClass tc = new TestBClass();
		CallBack callback = new CallBack(tcb, tcb.getClass().getMethod("AddProduct", int.class, int.class));
		tc.testCall(callback);
		for (int i : tcb.list) {
			System.out.println(i);
		}
		tcb.list.clear();
		System.out.println("-------");
		callback = new CallBack(tcb, tcb.getClass().getMethod("AddSum", int.class, int.class));
		tc.testCall(callback);
		for (int i : tcb.list) {
			System.out.println(i);
		}

执行结果:

0
2
6
12
20
30
42
56
72
90
-------
1
3
5
7
9
11
13
15
17
19

后记

目前发现invoke 不支持以String[]作为多态参数。可以转化为ArrayList传递

  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

墨烬

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值