在C语言中,函数名可以当做函数指针传递给形参从而实现回调

void f1() { printf("f1()\n"); }
void f2() { printf("f2()\n"); }
void f3() { printf("f3()\n"); } void do_func(void(*f)()) { f(); } int main()
{
do_func(f1);
do_func(f2);
do_func(f3);
}

在C++11中,实现回调还可以通过函数模板和lambda表达式的方式

template <typename Func>
void do_func(Func f) { f(); } int main()
{
do_func([]() { printf("f1()"); });
do_func([]() { printf("f2()"); });
do_func([]() { printf("f3()"); });
}

而假如回调函数的代码实现较为复杂,且具有重用价值,lambda表达式这种一次性的方案就不太适合,在C++11之前,是通过函数对象来实现的。函数对象说白了就是一个类的普通对象,只不过C++可以重载括号运算符,导致调用类的对象的operator()方法时,就像调用函数一样自然。

而分析本质,其实回调函数就是一种函数签名(若干个输入参数、一个输出参数)的规范,java虽不存在函数声明,但是java可以用接口来强制规范。

interface Funcable {
void Func();
}

这样只要实现了该接口的类,都有一个函数签名和void Func()一致的成员函数(嘛,还是不习惯方法(method)这种叫法),于是只需要把实现了该接口的类的对象传入函数中,然后在函数中调用该对象的Func()方法即可

class F1 implements Funcable {

    @Override
public void Func() {
System.out.println("f1()");
} } public class Test { public static void do_func(Funcable funcable) {
funcable.Func();
} public static void main(String[] args) {
do_func(new F1());
}
}

这里节省代码量,就不把类F2、F3给写出来了。并且利用java的匿名类可以节省代码,类似于lambda表达式

        do_func(new Funcable() {
@Override
public void Func() {
System.out.println("f2()");
}
});

说到lambda表达式,它是可以捕获外部变量的,在Java这种方式还可以通过匿名内的匿名构造函数来显式捕获外部的变量

        String msg = "f3()";
do_func(new Funcable() {
String _msg; {
_msg = msg;
} @Override
public void Func() {
System.out.println(_msg);
}
});

这种做法就很像lambda表达式了,因为匿名类的匿名构造函数是只能以外部变量为构造参数的,相当于lambda表达式的“捕获”,对应C++的lambda表达式写法就是

    std::string msg = "f3()";
do_func([&msg]() { std::cout << msg << std::endl; });

java8也有lambda表达式了,因此可以写成这样

do_func(() -> { System.out.println(msg); });

Java通过匿名类来实现回调函数的更多相关文章

  1. 【java回调】java两个类之间的回调函数传递

    背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...

  2. Java JNA (二)—— dll回调函数实现

    java调用dll文件需要使用回调函数作为公开函数的参数时,用以下方法实现: 首先,看c++中定义的dll公开函数: typedef void (*ccback)(char *name ,int le ...

  3. 浅谈Java的匿名类

    在实际的项目中看到一个很奇怪的现象,Java可以直接new一个接口,然后在new里面粗暴的加入实现代码.就像下面这样.那么问题来了,new出来的对象没有实际的类作为载体,这不是很奇怪吗? 思考以下代码 ...

  4. java:使用匿名类直接new接口

    java中的匿名类有一个倍儿神奇的用法,见下面代码示例: package contract; public interface ISay { void sayHello(); } 上面是一个简单的接口 ...

  5. Java之匿名类讲解

    参考https://blog.csdn.net/jiaotuwoaini/article/details/51542059 匿名类,正如名字一样在java中没有名字标识的类,当然了编译后还是会安排一个 ...

  6. Java中Collections类的排序sort函数两种用法

    java中的Colletions类主要实现列表List的排序功能.根据函数参数的传递,具体的排序可以分为 : 1.  自然排序(natural ordering). 函数原型:sort(List< ...

  7. Java中匿名类的两种实现方式(转)

    使用匿名内部类课使代码更加简洁.紧凑,模块化程度更高.内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到.然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式 ...

  8. Java 在匿名内部函数中为外部函数变量赋值的解决方案

    Java匿名内部函数本人不怎么主动使用,但是经常会调用一些API,其中会调用一些接口,而这些接口是需要使用匿名内部类来实现的,于是就遇到了一些问题. 就比如okHttp3 的接口调用 OkHttpCl ...

  9. java中匿名类的讲解

    匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象 ...

随机推荐

  1. 2017-2018-1 JaWorld 团队作业--冲刺3

    2017-2018-1 JaWorld 团队作业--冲刺3 (20162306) 总体架构 我们本次团队项目设定为基于Android系统Java架构下的打飞机小游戏 游戏中所有模型的原型设定是精灵,因 ...

  2. Android 开机Process xxx (pid xxxx) has died问题分析

    系统中有一个监听BOOT_COMPLETED广播的自启应用,概率性出现启动后被kill掉的现象.Log如下: - :: I ActivityManager: Process com.test.xxx ...

  3. linux内核启动时报错ubi0 error: validate_ec_hdr: bad VID header offset 256, expected 64

    1.详细错误报告如下: ubi0 error: validate_ec_hdr: bad VID header offset 256, expected 64 ubi0 error: validate ...

  4. 2018-2019 Russia Open High School Programming Contest (Unrated, Online Mirror, ICPC Rules, Teams Preferred)

    前言 有一场下午的cf,很滋磁啊,然后又和dalao(见右面链接)组队打了,dalao直接带飞我啊. 这是一篇题解,也是一篇总结,当然,让我把所有的题目都写个题解是不可能的了. 按照开题顺序讲吧. 在 ...

  5. python2.7和python3.6共存,使用pip安装第三方库

    因为一般情况下,window命令行运行pip,默认的情况是运行python3.6的pip,安装第三方库的路径也是python3.6,安装路径是: 如何运行在2.7环境下安装PIP呢?有网上的教程说需要 ...

  6. DDMS

    DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务

  7. Chain of Responsibility(责任链)

    意图: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 适用性: 有多个的对象可以处理一个请求,哪个对 ...

  8. 关于java中ArrayList的快速失败机制的漏洞——使用迭代器循环时删除倒数第二个元素不会报错

    一.问题描述 话不多说,先上代码: public static void main(String[] args) throws InterruptedException { List<Strin ...

  9. Libpacp 深度剖析

    Libpacp 深度剖析 1. Libpacp 的工作原理 ​ Libpcap的工作原理可以描述为,当一个数据包到达网卡时,通过网络分接口(即旁路机制)将数据包发给BPF过滤器,匹配通过的数据包可以被 ...

  10. 2-14-1 MySQL基础语句,查询语句

    一. SQL概述 结构化查询语言(Structured Query Language)简称SQL 1. 它是一种特殊目的的编程语言 2. 它还是一种数据库查询和程序设计语言 (用于存取数据以及查询.更 ...