一、前言
在传统的 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函数作为参数传递内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论