使用不同的异常类型编写两个函数(java泛型)

时间:2018-04-27 15:52:36

标签: java generics functional-interface

假设我想实现一个java.util.function.Function<T,R>版本,可以抛出一些异常类型E。我所做的是创建一个名为ThrowingFunction的功能接口,如下所示:

@FunctionalInterface
interface ThrowingFunction<T, R, E extends Exception>
{
    R apply(T t) throws E;
}

就像在java.util.function.Function<T,R>中一样,我需要实现默认方法compose,我需要的是组合两个不同的ThrowingFunction个实例,并且可能会有一个不同的抛出异常类型。所以这是我的尝试:

default <V, E1 extends Exception, E2 super E1 & E> ThrowingFunction<V, R, E2> compose(ThrowingFunction<? super V, ? extends T, ? extends E1> before)
{
    return v -> apply(before.apply(v));
}

当然,我遇到编译错误:

  

令牌“super”上的语法错误,扩展了预期

完全在通用参数E2 super E1 & E的声明中。

那么,这个问题的可能解决方案是什么,我只是编写两个具有相同异常类型ThrowingFunction的不同E个实例(,这不是最好想要的) em>)?

1 个答案:

答案 0 :(得分:2)

您不能在此处使用default方法;它必须是接口上的static方法。当您尝试使用default方法时,已经捕获了类型E,并且Java编译器将不允许您将类型E2声明为更少的类型的超类型2种类型EE1,正如您的编译器错误所示。

更改为static方法时,您可以根据需要自由声明异常类型参数。您可以声明超类型异常类型S,然后是子类型异常类型E1E2。然后其余部分与Function的默认compose方法类似。

此处的类型参数与Function.compose使用的内容相匹配,并添加了与异常相关的类型参数。

@FunctionalInterface
interface ThrowingFunction<T, R, E extends Exception>
{
    R apply(T t) throws E;

    /**
     * Composes f (after) and g (before) to produce the composed
     * function f o g(v), which executes f(g(v)).
     * @param f The function that will take g's output <T> as input to return the overall result <R>.
     * @param g The function that will take the overall input <V> and return f's input <T>.
     * @param <V> The input result type of the entire composed function (and of function g).
     * @param <T> The result type of g, used as input to f.
     * @param <R> The end result type of the entire composed function (and of function f).
     * @param <S> If any of f or g throws an exception, it is captured by the supertype exception class S.
     * @param <E1> The exception type thrown by f.
     * @param <E2> The exception type thrown by g.
     * @return A ThrowingFunction that whose input <V> is applied to g, whose result is passed to
     *     f to generate the overall result <R>.
     */
    static <V, T, R, S extends Exception, E1 extends S, E2 extends S> ThrowingFunction<V, R, S>
        compose(ThrowingFunction<? super T, ? extends R, ? extends E1> f,
                ThrowingFunction<? super V, ? extends T, ? extends E2> g)
    {
        return v -> f.apply(g.apply(v));
    }
}