apply方法严格按BiFunction<T,U,R>接口要求接收两个参数并返回单一结果,不自动解包、不隐式转换、不校验空值,类型匹配和逻辑由用户定义,无状态、无拦截、不可隐式转型。
apply 方法直接接收两个参数,按声明顺序传入,执行逻辑后返回单一结果。 它不自动解包、不隐式转换、不校验空值——所有行为都由你写的 lambda 或方法引用决定。关键在于类型匹配和逻辑聚焦。
参数顺序和类型必须严格对应接口声明
BiFunction<T, U, R> 的 apply(T t, U u) 要求:第一个实参类型必须是 T,第二个必须是 U。比如:
- BiFunction<String, Integer, User> creator = User::new; —— 构造器必须接受 String 作第一参、Integer 作第二参,否则编译失败
- BiFunction<List<String>, Integer, String> getNth = (list, idx) -> list.get(idx); —— 若传入 (idx, list),类型错位,编译报错
执行过程就是一次函数调用,无额外包装或调度
apply 不做拦截、不加日志、不重试。它等价于手动调用你定义的逻辑:
- BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
调用 add.apply(3, 5) 就是直接计算 3 + 5,返回 8 - BiFunction<User, String, Boolean> hasRole = (u, r) -> u != null && u.getRoles().contains(r);
调用时若 u 为 null,就会触发 NullPointerException —— 空安全需自行处理
返回值类型由泛型 R 决定,不可隐式转型
编译器强制返回值必须是 R 类型或其子类。常见误用:
立即学习“Java免费学习笔记(深入)”;
- 声明为 BiFunction<String, String, Number>,却在 lambda 中返回 "123"(String 不是 Number 子类)→ 编译失败
- 正确写法:BiFunction<String, String, String> concat = (a, b) -> a + b; 或 BiFunction<String, String, Number> lenSum = (a, b) -> a.length() + b.length();
它不维护状态,每次 apply 都是独立计算
BiFunction 实例本身无成员变量,不记录上次调用结果。适合纯函数场景:
- 可安全共享、复用、传递给 Stream.map
- 无法靠自身实现“累计求和”或“记住上一个输入”,这类需求需配合外部变量或改用其他结构