JDK8新特性之函数式接口
时间:2022-05-06
本文章向大家介绍JDK8新特性之函数式接口,主要内容包括什么是函数式接口、内置函数式接口、自定义函数式接口、函数式接口规范、举例说明、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
什么是函数式接口
先来看看传统的创建线程是怎么写的
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
t1.start();
再来看看使用了函数式接口是怎么写的
Thread t2 = new Thread(() -> System.out.println("t2"));
t2.start();
Runnable接口直接可以使用Lambda表达式来编写,这是因为Runnable接口是一个函数式接口,来看看Runnable的源码。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
发现该接口加上了函数式接口的定义注解: @FunctionalInterface
,表明该接口是一个函数式接口。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {
}
在JDK8中,除了Runnbale接口,还有像Comparator、Callable等接口都加上了该注解定义为函数式接口。
内置函数式接口
JDK8提供了几个内置的函数式接口,用在了许多API的地方,都可以拿来用,可以满足大部分应用。
//Consumer<T> - T作为输入,执行某种动作但没有返回值
Consumer<String> con = (x) -> {
System.out.println(x);
};
con.accept("hello world");
//Supplier<T> - 没有任何输入,返回T
Supplier<String> supp = () -> {
return "Supplier";
};
System.out.println(supp.get());
//Predicate<T> -T作为输入,返回的boolean值作为输出
Predicate<String> pre = (x) -> {
System.out.print(x);
return x.startsWith("op");
};
System.out.println(": " + pre.test("op, hello World"));
// Function<T, R> -T作为输入,返回的R作为输出
Function<String, String> function = (x) -> {
System.out.print(x + ": ");
return "Function";
};
System.out.println(function.apply("hello world"));
//BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
BinaryOperator<String> bina = (x, y) -> {
System.out.print(x + " " + y);
return "BinaryOperator";
};
System.out.println(" " + bina.apply("hello ", "world"));
自定义函数式接口
1、自定义一个函数式接口
@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
}
这里只有一个抽象方法,@FunctionalInterface注解可以不用写,至于为什么可以往下看。
2、新建一个引用函数式接口的类
public static class NumberOperation<N extends Number, V extends Number> {
private N n1;
private N n2;
public NumberOperation(N n1, N n2) {
this.n1 = n1;
this.n2 = n2;
}
public V calc(CalcInterface<N, V> ci) {
V v = ci.operation(n1, n2);
return v;
}
}
3、测试函数式接口
private static void testOperationFnInterface() {
NumberOperation<Integer, Integer> np = new NumberOperation(13, 10);
CalcInterface<Integer, Integer> addOper1 = (n1, n2) -> {
return n1 + n2;
};
CalcInterface<Integer, Integer> multiOper1 = (n1, n2) -> {
return n1 * n2;
};
System.out.println(np.calc1(addOper1));
System.out.println(np.calc1(multiOper1));
// 上面的可以简写为
System.out.println(np.calc1((n1, n2) -> n1 + n2));
System.out.println(np.calc1((n1, n2) -> n1 * n2));
}
最后输出:
23
130
23
130
函数式接口规范
1、@FunctionalInterface标识为一个函数式接口只能用在只有一个抽象方法的接口上。
2、接口中的静态方法、默认方法、覆盖了Object类的方法都不算抽象方法。
3、@FunctionalInterface注解不是必须的,如果该接口只有一个抽象方法可以不写,它默认就符合函数式接口,但建议都写上该注解,编译器会检查该接口是否符合函数式接口的规范。
举例说明
正确的函数式接口。
@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
}
加了几个符合函数式的方法也没事,编译器也不会报错。
@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
public boolean equals(Object object);
public default void defaultMethod() {
}
public static void staticMethod() {
}
}
这个没用@FunctionalInterface函数式接口,有两个抽象方法,不能用于Lambda表达式。
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
V operation2(N n1, N n2);
}
这个有两个抽象方法的用@FunctionalInterface注解的函数式接口编译会报错。
@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
V operation2(N n1, N n2);
}
这个没有一个抽象方法,编译报错。
public interface CalcInterface<N, V> {
}
- 移动Web 开发中的 Off Canvas 导航
- Angularjs基础(八)
- 移动Web 开发中的一些前端知识收集汇总
- Angularjs基础(七)
- WordPress 中八个有用的代码片段
- 【释疑文】DeveMobile、EaseMobile 及Devework 主题的区别
- DeveMobile/EaseMobile 主题双双更新1.1,增加离线存储,社交媒体关注等功能
- Angularjs基础(六)
- 如果机器人拥有痛觉,这个世界会怎样
- 阻止iOS Web APP中点击链接跳转到Safari 浏览器新标签页
- 专门攻击工资支付系统的网络犯罪
- Angularjs基础(五)
- DW Replace Open Sans:将WordPress 后台中的open-sans字体加载源从Google Fonts换为360 CDN
- Google Fonts 已可正常访问,相关插件可卸
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 爬取bilibili再也不用头疼了,bilibili-api一步到位!
- 「React」很多人在滥用 state
- == 与equals和hashCode与equals
- 算法集锦(10)| 自动驾驶、机器人 | 物品图像动态检测算法实现
- Hystrix仪表盘
- Centos7 Nginx的SSL证书安装
- 算法集锦(11)| 自动驾驶 | 基于HOG和SVM的车辆识别算法
- 剑指offer(一):找出数组中重复的数字
- 剑指offer(二):不修改数组找出重复的数字
- 漫画:什么是树状数组?
- poiAndEasyExcel学习(五)
- 两分钟真能搞懂桶排序
- SpringMVC文件上传下载
- 学弟不懂原码反码补码,气的我给女朋友讲了一夜
- 使用 HanLP 统计二元语法中的频次