【Java】Java 中函数作为参数传递详解

文章目录
- 一、前言
- 二、为什么要把函数作为参数传递?
- 三、实现函数传参的关键:函数式接口
- 函数式接口定义
- 四、JDK 内置的函数式接口
- Consumer 示例
- Function 示例
- Predicate 示例
- Supplier 示例
- 五、结合方法引用(`::`)的写法
- 六、Stream API 中的函数传参
- 七、总结
- 八、参考资料
一、前言
在传统的 Java 开发中,我们习惯将数据作为参数传递给方法。
但从 Java 8 开始,Java 引入了 Lambda 表达式 和 方法引用,
让我们能够像在函数式语言中那样,把“函数(行为)”本身作为参数进行传递。
这种特性让 Java 更加灵活、简洁,也极大地推动了 函数式编程(Functional Programming) 在 Java 中的应用。
二、为什么要把函数作为参数传递?
在面向对象编程中,我们常常写这样的代码:
public void process(String input) {System.out.println(input.toUpperCase());
}
如果你想对 input 做不同的处理逻辑,比如转小写、反转、加前缀……
通常要写多个方法,或者在方法内部用 if/else。
但如果我们能将“处理逻辑”作为函数传入,就可以让方法更通用:
public void process(String input, Function<String, String> operation) {System.out.println(operation.apply(input));
}
于是我们就能这样灵活调用:
process("Java", s -> s.toUpperCase()); // 转大写
process("Java", s -> s.toLowerCase()); // 转小写
process("Java", s -> "Hello " + s); // 加前缀
是不是非常优雅?这就是“函数作为参数传递”的威力。
三、实现函数传参的关键:函数式接口
在 Java 中,函数不是一等公民,不能直接像 Python 那样传递函数。
但 Java 通过 函数式接口(Functional Interface) 实现了类似功能。
函数式接口定义
函数式接口就是只包含一个抽象方法的接口。
例如:
@FunctionalInterface
interface MyOperation {void execute();
}
然后我们就可以传入一个 Lambda 表达式:
public class Demo {public static void main(String[] args) {doSomething(() -> System.out.println("Hello Lambda!"));}public static void doSomething(MyOperation op) {op.execute(); // 调用传入的函数}
}
输出:
Hello Lambda!
四、JDK 内置的函数式接口
Java 在 java.util.function 包中已经内置了大量常用函数式接口。
| 接口名 | 方法签名 | 功能说明 |
|---|---|---|
Consumer<T> | void accept(T t) | 接收一个参数,无返回值 |
Supplier<T> | T get() | 无参数,有返回值 |
Function<T, R> | R apply(T t) | 接收参数并返回结果 |
Predicate<T> | boolean test(T t) | 接收参数并返回布尔值 |
Consumer 示例
import java.util.function.Consumer;public class ConsumerDemo {public static void main(String[] args) {processData("Java", s -> System.out.println("Hello, " + s + "!"));}public static void processData(String data, Consumer<String> action) {action.accept(data);}
}
输出:
Hello, Java!
Function 示例
import java.util.function.Function;public class FunctionDemo {public static void main(String[] args) {transform("Lambda", s -> s.toUpperCase());transform("World", s -> "Hello " + s);}public static void transform(String data, Function<String, String> func) {String result = func.apply(data);System.out.println(result);}
}
输出:
LAMBDA
Hello World
Predicate 示例
import java.util.function.Predicate;public class PredicateDemo {public static void main(String[] args) {check("OpenAI", s -> s.length() > 5);check("GPT", s -> s.startsWith("G"));}public static void check(String data, Predicate<String> condition) {System.out.println(condition.test(data));}
}
输出:
true
true
Supplier 示例
import java.util.function.Supplier;public class SupplierDemo {public static void main(String[] args) {printValue(() -> "Hello from Supplier!");}public static void printValue(Supplier<String> supplier) {System.out.println(supplier.get());}
}
输出:
Hello from Supplier!
五、结合方法引用(::)的写法
当传入的 Lambda 只是调用某个已有方法时,可以用 方法引用 简化:
import java.util.List;public class MethodRefDemo {public void print(String s) {System.out.println("Item: " + s);}public void printAll(List<String> list) {// 等价于 list.forEach(s -> this.print(s));list.forEach(this::print);}public static void main(String[] args) {new MethodRefDemo().printAll(List.of("Java", "Python", "C++"));}
}
输出:
Item: Java
Item: Python
Item: C++
六、Stream API 中的函数传参
函数式接口的最大用途之一,就是在 Stream API 中传递行为逻辑。
import java.util.List;public class StreamExample {public static void main(String[] args) {List<String> names = List.of("Alice", "Bob", "Charlie", "David");names.stream().filter(name -> name.length() > 3) // 传入 Predicate.map(String::toUpperCase) // 传入 Function.forEach(System.out::println); // 传入 Consumer}
}
输出:
ALICE
CHARLIE
DAVID
这就是 Java 函数式编程的典型应用场景。
七、总结
| 概念 | 说明 |
|---|---|
| 函数式接口 | 只包含一个抽象方法的接口,用于支持 Lambda 表达式 |
| Lambda 表达式 | 让你能像传递数据一样传递行为 |
方法引用 (::) | Lambda 的简写方式,可直接引用已有方法 |
| 常用接口 | Consumer、Supplier、Function、Predicate |
| 典型应用 | Stream API、回调函数、异步任务等 |
八、参考资料
Java-函数作为参数的传递与使用_java 函数参数-CSDN博客
Python中将函数作为参数传递给函数
