Java8函数接口实现回调及Groovy闭包的代码示例
本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋。
概述###
在实际开发中,常常遇到使用模板模式的场景: 主体流程是不变的,变的只是其中要调用的具体方法。 其特征是:
BeginTodo ---> Something different to do ---> others todo ---> End
其中BeginTodo ,others todo,End 都是不变的,只有 Something different to do 是根据业务变化的。 如果采用 Java 来实现,通常要为 Something different to do 定义回调接口 Callback , 然后在主体流程中调用这个回调接口,而在实际业务中,创建 Callback 的实现类传入进去。
Java8 Function 以及闭包对此提供了更为简洁方便的语言支持。 Function 是Java8对函数的抽象,用于描述和接收任何单参数单返回的函数,类似于 Callback 的作用; 而在使用的时候,只要将方法引用或 lambda 表达式传给 Function 即可。
代码示例###
举例来说,要编写一个通用方法,实现多次执行同一个测试方法,统计失败次数。
Java-Function####
package com.xxx.trade;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.junit.Test;
import java.util.function.Function;
/**
* Created by shuqin on 16/11/15.
*/
public class GeneralExecTestMoreTimes extends TestCase {
public void execMoreTimes(Function f) {
execMoreTimes(f, new Object());
}
public void execMoreTimes(Function f, int num) {
execMoreTimes(f, null, num);
}
public void execMoreTimes(Function f, Object t) {
execMoreTimes(f, t, 20);
}
public void execMoreTimes(Function f, Object t, int num) {
int failed = 0;
for (int i = 0; i < num; i++) {
try {
f.apply(t);
} catch (AssertionFailedError afe) {
failed += 1;
} catch (Exception ex) {
failed += 1;
}
}
System.out.println("----- failed: " + failed + " -----");
assertEquals(0, failed);
}
@Test
public void testExecMoreTimes() {
execMoreTimes((o) -> {
System.out.println("haha");
return 1;
}, 5);
}
}
这里 execMoreTimes 方法接收一个函数式接口 Function 以及将应用于的参数 t 。 那么什么可以传给 Function 接口呢? 可以是任何单参数单返回值的函数,或者单参数单返回值的 lambda 表达式。例如代码中的 (o) -> { // some codes } 。
Groovy闭包####
如果使用 Groovy 编写闭包,会更简洁: 只要定义一个由大括号 {} 包围的代码块,并赋给一个变量即可(如下面的test1),甚至可以直接在函数里调用一个由大括号包围的代码块参数(如下面的test2)。 这样, 使用代码块或函数就会更加直接、灵活、自由,而不会受制于语法,也不需要定义一堆接口了。
package com.xxx.trade
import org.junit.Test
/**
* Created by shuqin on 16/11/15.
*/
class GeneralExecTestMoreTimesTest extends GeneralExecTestMoreTimes {
@Test
public void test1() {
def closure = {
System.out.println("here is test")
}
execMoreTimes(closure)
}
@Test
public void test2() {
execMoreTimes({
throw new Exception("throw exception in test")
})
}
}
应用场景####
函数接口可以用于任何使用回调接口的场景,一个典型的应用场景是批量处理。 比如有三个小组对同一个列表进行处理,一个用于状态同步,一个用于退款,一个用于取消。 那么,可以实现一个批量处理的通用函数,然后调用三个小组的自定义函数即可。
package zzz.study.utils;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
/**
* Created by shuqin on 17/1/19.
*/
public class BatchProcessUtil {
public static String batchProcessOrders(Consumer<String> processFunction, List<String> orders) {
StringBuilder result = new StringBuilder();
for (String orderNo: orders) {
String orderNoTrimed = orderNo.trim();
try {
processFunction.accept(orderNo);
result.append(orderNoTrimed + " OK , 请稍后查看!\n");
} catch (Exception e) {
result.append(orderNoTrimed + " Failed, 请稍后重试!\n");
}
}
return result.toString();
}
public static void sync(String orderNo) {
System.out.println("sync order state " + orderNo);
}
public static void refund(String orderNo) {
System.out.println("refund for " + orderNo);
}
public static void cancel(String orderNo) {
System.out.println("cancel " + orderNo);
}
public static void main(String[] args) {
List<String> orders = Arrays.asList(new String[] {"E001", "E002", "E003"});
batchProcessOrders((orderNo) -> sync(orderNo), orders);
batchProcessOrders((orderNo) -> refund(orderNo), orders);
batchProcessOrders((orderNo) -> cancel(orderNo), orders);
}
}
输出是
sync order state E001
sync order state E002
sync order state E003
refund for E001
refund for E002
refund for E003
cancel E001
cancel E002
cancel E003
常用函数接口###
常用函数接口主要有:
- Consumer (接收单参数无返回值的函数或lambda表达式), 方法是 void accept(T t);
- BiConsumer<T, U> (接收双参数无返回值的函数或 lambda表达式),方法是 void accept(T t, U u) ;
- Function<T, R> (接收单参数有返回值的函数或lambda表达式), 方法是 R apply(T t);
- BiFunction<T, U, R> (接收双参数有返回值的函数或lambda表达式),方法是 R apply(T t, U u);
- Predicate (接收单参数返回布尔值的函数或lambda表达式),方法是 boolean test(T t);
- Supplier (无参数返回值的函数或 lambda), 方法是 T get();
- 接受原子类型参数的函数接口,这里不一一列举了。可参考 java8 package java.util.function;
小结###
为什么要使用 Function 以及闭包呢?
- 在语法上比定义回调接口、创建匿名类更加简洁;
- 尝试使用新的语言特性,理解多样化的编程思想,提升编程表达能力。
Java8函数接口实现回调及Groovy闭包的代码示例的更多相关文章
- Java8-Function使用及Groovy闭包的代码示例
导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...
- java8 函数接口 Predicate例子
import java.util.HashSet; import java.util.Collection; import java.util.function.Predicate; public c ...
- java8 函数接口
[前言] java8新特性 java8 Optional使用总结 java8 lambda表达式 Java 8 时间日期使用 1.函数式接口新特性 java8中引入了函数式接口新特性,使用@Funct ...
- 开始Java8之旅(四) --四大函数接口
前言 Java8中函数接口有很多,大概有几十个吧,具体究竟是多少我也数不清,所以一开始看的时候感觉一脸懵逼,不过其实根本没那么复杂,毕竟不应该也没必要把一个东西设计的很复杂. 几个单词 在学习 ...
- [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...
- Java8函数之旅(四) --四大函数接口
前言 Java8中函数接口有很多,大概有几十个吧,具体究竟是多少我也数不清,所以一开始看的时候感觉一脸懵逼,不过其实根本没那么复杂,毕竟不应该也没必要把一个东西设计的很复杂. 几个单词 在学习 ...
- Java8学习笔记(二)--三个预定义函数接口
三个函数接口概述 JDK预定义了很多函数接口以避免用户重复定义.最典型的是Function: @FunctionalInterface public interface Function<T, ...
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...
- java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口
函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...
随机推荐
- 【咸鱼教程】一个简单的弹出二级菜单UIPopupMenu
一. 实际效果 演示地址 二.实现原理主要用Button+List组件,和遮罩实现. 1. 点击Button时,将List下移展开.2. 再次点击Button,或者选中List中的某一项时,将List ...
- C# 压缩文件 ICSharpCode.SharpZipLib.dll
效果: 代码只能压缩文件夹里面的文件,不能压缩文件夹. 压缩前: 压缩后: 代码: 需要引用ICSharpCode.SharpZipLib.dll public ActionResult Index( ...
- Unity3D笔记 GUI 四、实现选项卡三
一.代码: using UnityEngine; using System.Collections; /// <summary> /// 选项卡二 /// </summary> ...
- vue--父组件主动获取子组件的方法
父组件主动获取子组件的方法和属性 第一步:调用自组件的时候,给自组建定义一个Header <v-header ref='headerInfo'></v-header> 第二步: ...
- 2-sat入门(tarjan)hdu(3062)
hdu3062 Party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- Java Mail 发送邮件(SSL加密方式,TSL加密方式)
一.一般配置 发送邮件需要用到 mail包 maven 依赖如下: <!-- https://mvnrepository.com/artifact/javax.mail/mail --> ...
- Java、JavaWeb中单元测试用到的测试方法
写出的代码做单元测试时,一定要记住从三个方面出发:1.成功 2.异常 3 逻辑错误(即没有异常也可能程序运行出最后结果,可是呢?呵呵).这就是在做测试时我要牢记的三个方面,同时思维要严谨也即做事要 ...
- FZU 2092 收集水晶(记忆化搜索)
Problem 2092 收集水晶 Accept: 101 Submit: 439 Time Limit: 5000 mSec Memory Limit : 32768 KB Problem Desc ...
- POJ 3580 - SuperMemo - [伸展树splay]
题目链接:http://poj.org/problem?id=3580 Your friend, Jackson is invited to a TV show called SuperMemo in ...
- ArcGIS API for javascript开发笔记(四)——GP服务调用之GP模型的规范化制作详解
感谢一路走来默默陪伴和支持的你~~~ -------------------欢迎来访,拒绝转载------------------- 在之前的利用Python分析GP服务运行结果的输出路径 & ...