假设我想实现一个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>)?
答案 0 :(得分:2)
您不能在此处使用default
方法;它必须是接口上的static
方法。当您尝试使用default
方法时,已经捕获了类型E
,并且Java编译器将不允许您将类型E2
声明为更少的类型的超类型2种类型E
和E1
,正如您的编译器错误所示。
更改为static
方法时,您可以根据需要自由声明异常类型参数。您可以声明超类型异常类型S
,然后是子类型异常类型E1
和E2
。然后其余部分与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));
}
}