Java中将某个方法当做参数传入另一个方法的实现
1、需求
最近工作中遇到一个情况,需要写6个很相似的查询功能,着6个查询的唯一的区别就是返回实体的字段不相同。
例如:我的待办需求,待办查询方式是一样的,但是待办分为好多种类型,每种类型的列表展示信息又是不一致的。
考虑到代码复用,打算写一个公共的查询方法,返回一个泛型,并且将最后组装返回实体的逻辑由上层的方法进行传入,由调用端指定公共方法内组装实体的逻辑以及返回的类型。
2、实现(函数式编程)-如果直接想要看简单示例,直接拉到第3点,有各种简单示例
2.1、先定义了一个带有泛型参数的函数式接口 TodoFunction
函数式接口需要加上@FunctionalInterface注解,接口中定义一个execute方法,传入一个查询结果queryList和一个返回结果result,代码如下:
@FunctionalInterface public interface TodoListFunction<T> { void execute(List<Map<String, String>> queryList, List<T> result); }
2.2、写两个具体的业务方法实现上述execute方法(不需要继承)
实现不同类型待办的实体赋值逻辑,代码如下:
/** * 代办A */ public class ATodoService { /** * 代办A. * @param queryList * @param result */ public static void execute(List<Map<String, String>> queryList, List<ATodoDto> result) { // 此处可以执行自己的一些特有逻辑 // ... for (var queryItem : queryList) { var item = new ATodoDto(); item.setA(queryItem.get("A")); item.setB(queryItem.get("B")); result.add(item); } } } /** * 代办B */ public class BTodoService { /** * 代办B. * @param queryList * @param result */ public static void execute(List<Map<String, String>> queryList, List<BTodoDto> result) { // 此处可以执行自己的一些特有逻辑 // ... for (var queryItem : queryList) { var item = new BTodoDto(); item.setC(queryItem.get("C")); item.setD(queryItem.get("D")); result.add(item); } } }
2.3、写一个处理公共逻辑的方法,并且将2.1定义的TodoFunction作为参数传入
/** * 代办查询 * @param request * @return */ private <T> List<T> getTodoList(List<Map<String, String>> queryList, TodoListFunction todoMethod) { // 处理一些公共逻辑 // TODO ...... List<T> result = new ArrayList<>(); // 执行具体方法(会根据实际上端根据传入的方法进行执行) todoMethod.execute(queryList, result); return result; }
2.4、上端调用
/** * 获取A代办 * @param request * @return */ public List<ATodoDto> getATodoList(List<Map<String, String>> queryList) { return getTodoList(queryList, ATodoService::execute); } /** * 获取B代办 * @param request * @return */ public List<BTodoDto> getBTodoList(List<Map<String, String>> queryList) { return getTodoList(queryList, BTodoService::execute); }
总结:这里A待办和B待办共同调用getTodoList方法,但是传入的execute方法不同,最终在getTodoList方法中执行不同的execute方法,从而满足我们的需求
3、Java中各种函数式编程实现示例
3.1、不带参数方式(Runnable 为自带类)
public class Main { public static void main(String[] args) { executeMethod(() -> { System.out.println("Hello, World!"); }); } public static void executeMethod(Runnable method) { // 在被传入的方法内执行传入的方法 method.run(); } }
在上述示例中,定义了一个 executeMethod() 方法,它接收一个 Runnable 参数,即一个函数式接口。然后,在 main() 方法中调用 executeMethod() 方法,并通过 Lambda 表达式传入一个方法的实现。在被传入的方法 executeMethod() 中,通过调用 Runnable 接口的 run() 方法来执行传入的方法。
3.2、带一个参数方式
import java.util.function.Consumer; public class Main { public static void main(String[] args) { executeMethod("Hello, World!", message -> { System.out.println("Received message: " + message); }); } public static void executeMethod(String message, Consumer<String> method) { // 在被传入的方法内执行传入的方法,并传递参数 method.accept(message); } }
在上述示例中,定义了一个 executeMethod() 方法,它接收一个字符串参数 message 和一个 Consumer<String> 参数 method,即接受一个字符串参数并返回 void 的函数式接口。然后,在 main() 方法中调用 executeMethod() 方法,并通过 Lambda 表达式传入一个带参数的方法实现。在被传入的方法 executeMethod() 中,通过调用 Consumer 接口的 accept() 方法来执行传入的方法,并传递参数。
3.3、带多个参数方式
@FunctionalInterface interface MyFunction { void execute(int a, int b, String message); } public class Main { public static void main(String[] args) { executeMethod(10, 20, "Hello", (a, b, message) -> { System.out.println("Received parameters: a = " + a + ", b = " + b + ", message = " + message); }); } public static void executeMethod(int a, int b, String message, MyFunction method) { // 在被传入的方法内执行传入的方法,并传递参数 method.execute(a, b, message); } }
3.4、泛型并且带多个参数
@FunctionalInterface interface MyFunction<T> { void execute(T value, int a, int b); } public class Main { public static void main(String[] args) { executeMethod("Hello", 10, 20, (value, a, b) -> { System.out.println("Received parameters: value = " + value + ", a = " + a + ", b = " + b); }); } public static <T> void executeMethod(T value, int a, int b, MyFunction<T> method) { // 在被传入的方法内执行传入的方法,并传递参数 method.execute(value, a, b); } }
3.5、泛型并且带多个参数(非Lambda方式),毕竟实际业务中逻辑比较复杂, 不可能在一个Lambda里面写上很多业务逻辑
@FunctionalInterface interface MyFunction<T> { void execute(T value, int a, int b); } public class Main { public static void main(String[] args) { executeMethod("Hello", 10, 20, Main::processParameters); } public static <T> void executeMethod(T value, int a, int b, MyFunction<T> method) { // 在被传入的方法内执行传入的方法,并传递参数 method.execute(value, a, b); } public static <T> void processParameters(T value, int a, int b) { System.out.println("Received parameters: value = " + value + ", a = " + a + ", b = " + b); } }