如何组合带有不同异常类型的两个函数(Java泛型)
实现ThrowingFunction的compose默认方法
这是个很实用的需求!要给你自定义的ThrowingFunction实现类似java.util.function.Function的compose默认方法,核心要兼顾类型兼容性和异常泛型的传递,同时遵循compose的核心逻辑:先执行传入的前置函数,再执行当前函数。
完整实现代码
import java.util.Objects; @FunctionalInterface interface ThrowingFunction<T, R, E extends Exception> { R apply(T t) throws E; // 实现compose默认方法 default <V, E1 extends Exception> ThrowingFunction<V, R, ? extends Exception> compose( ThrowingFunction<? super V, ? extends T, E1> before) { // 非空校验,和JDK原生Function实现保持一致 Objects.requireNonNull(before); // 组合逻辑:先执行前置函数,再用其结果执行当前函数 return v -> apply(before.apply(v)); } }
关键细节解释
泛型参数设计:
- 新增
<V>:代表前置函数的输入类型,和Function.compose的泛型定义对齐 - 新增
<E1 extends Exception>:代表前置函数可能抛出的异常类型,确保不同异常类型的组合兼容性
- 新增
参数类型约束:
ThrowingFunction<? super V, ? extends T, E1> before:? super V:允许前置函数接受V或其父类型的输入(协变输入),提升使用灵活性? extends T:允许前置函数返回T或其子类型的结果(逆变输出),符合JDK函数式接口的类型安全设计
返回类型:
ThrowingFunction<V, R, ? extends Exception>:组合后的函数可能抛出当前函数的E或前置函数的E1,用? extends Exception表示它是任意异常类型的子类;你也可以直接写成ThrowingFunction<V, R, Exception>(因为所有异常都继承自Exception),两种写法都能满足异常传递需求
方法体逻辑:
- 用lambda表达式简洁实现组合逻辑:先调用
before.apply(v)得到当前函数的输入参数,再执行当前函数的apply方法 - 自动传递异常:lambda中的两个
apply方法都声明了抛出异常,而返回的ThrowingFunction的apply方法也允许抛出Exception子类,因此无需额外捕获或包装异常,直接传递即可
- 用lambda表达式简洁实现组合逻辑:先调用
使用示例
import java.io.IOException; import java.sql.SQLException; public class ThrowingFunctionDemo { public static void main(String[] args) { // 示例1:将字符串转字节数组,可能抛出IOException ThrowingFunction<String, byte[], IOException> stringToBytes = s -> s.getBytes("UTF-8"); // 示例2:将字节数组转数据库存储字符串,可能抛出SQLException ThrowingFunction<byte[], String, SQLException> bytesToDbString = bytes -> { if (bytes.length == 0) throw new SQLException("Empty data can't be stored"); return new String(bytes); }; // 组合函数:先转字节数组,再转数据库字符串 ThrowingFunction<String, String, ? extends Exception> composed = bytesToDbString.compose(stringToBytes); // 使用时处理可能的异常 try { String result = composed.apply("Hello ThrowingFunction!"); System.out.println("Result: " + result); } catch (IOException | SQLException e) { System.err.println("Error occurred: " + e.getMessage()); e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者marsouf
相关产品推荐
相关产品推荐

