You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何组合带有不同异常类型的两个函数(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));
    }
}

关键细节解释

  1. 泛型参数设计:

    • 新增<V>:代表前置函数的输入类型,和Function.compose的泛型定义对齐
    • 新增<E1 extends Exception>:代表前置函数可能抛出的异常类型,确保不同异常类型的组合兼容性
  2. 参数类型约束:

    • ThrowingFunction<? super V, ? extends T, E1> before:
      • ? super V:允许前置函数接受V或其父类型的输入(协变输入),提升使用灵活性
      • ? extends T:允许前置函数返回T或其子类型的结果(逆变输出),符合JDK函数式接口的类型安全设计
  3. 返回类型:

    • ThrowingFunction<V, R, ? extends Exception>:组合后的函数可能抛出当前函数的E或前置函数的E1,用? extends Exception表示它是任意异常类型的子类;你也可以直接写成ThrowingFunction<V, R, Exception>(因为所有异常都继承自Exception),两种写法都能满足异常传递需求
  4. 方法体逻辑:

    • 用lambda表达式简洁实现组合逻辑:先调用before.apply(v)得到当前函数的输入参数,再执行当前函数的apply方法
    • 自动传递异常:lambda中的两个apply方法都声明了抛出异常,而返回的ThrowingFunction的apply方法也允许抛出Exception子类,因此无需额外捕获或包装异常,直接传递即可

使用示例

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:10:04