Java不允许我实现支持IOException的函数

时间:2017-04-30 06:44:46

标签: java function exception lambda

我试图创建一个允许通过该方法使用IOException的实现,但发生了一些奇怪的事情

/**
 * Represents a predicate (boolean-valued function) of two arguments. This is the two-arity specialization of {@link Predicate}.
 *
 * <p>
 * This interface is similar to {@link BiPredicate} except that it is allowed to throw an {@link IOException}.
 * </p>
 *
 * @param <T> the type of the first argument to the predicate
 * @param <U> the type of the second argument the predicate
 *
 * @author Magno N A Cruz
 * @see Predicate
 */
@FunctionalInterface
public interface IOBiPredicate<T, U> {

/**
 * Evaluates this predicate on the given arguments.
 *
 * @param t the first input argument
 * @param u the second input argument
 * @return {@code true} if the input arguments match the predicate, otherwise {@code false}
 * @throws IOException if there is an I/O error performing the operation.
 */
boolean test(T t, U u) throws IOException;

/**
 * Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another. When evaluating the composed predicate, if this
 * predicate is {@code false}, then the {@code other} predicate is not evaluated.
 *
 * <p>
 * Any exceptions thrown during evaluation of either predicate are relayed to the caller; if evaluation of this predicate throws an exception, the
 * {@code other} predicate will not be evaluated.
 * </p>
 *
 * @param other a predicate that will be logically-ANDed with this predicate
 * @return a composed predicate that represents the short-circuiting logical AND of this predicate and the {@code other} predicate
 * @throws NullPointerException if other is null
 */
default IOBiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
    Objects.requireNonNull(other);
    return (T t, U u) -> test(t, u) && other.test(t, u);
}

/**
 * Returns a predicate that represents the logical negation of this predicate.
 *
 * @return a predicate that represents the logical negation of this predicate
 */
default IOBiPredicate<T, U> negate() {
    return (T t, U u) -> !test(t, u);
}

/**
 * Returns a composed predicate that represents a short-circuiting logical OR of this predicate and another. When evaluating the composed predicate, if this
 * predicate is {@code true}, then the {@code other} predicate is not evaluated.
 *
 * <p>
 * Any exceptions thrown during evaluation of either predicate are relayed to the caller; if evaluation of this predicate throws an exception, the
 * {@code other} predicate will not be evaluated.
 * </p>
 *
 * @param other a predicate that will be logically-ORed with this predicate
 * @return a composed predicate that represents the short-circuiting logical OR of this predicate and the {@code other} predicate
 * @throws NullPointerException if other is null
 */
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
    Objects.requireNonNull(other);
    return (T t, U u) -> test(t, u) || other.test(t, u);
}

}

在lambda表达式(T t, U u) -> test(t, u) || other.test(t, u)上,条件的第一部分即test(t, u)给了我一个编译错误,说Unhandled exception type IOException,但第二个,即other.test(t, u)似乎工作正常,所以对我来说这是一个令人费解的情况,为什么它会发生在一个而不是另一个?

有没有一个干净的解决方案?如果没有,我怎么能修复它而不用计划上的kludges?

此问题类似于Java 8 Lambda function that throws exception?,但对于该问题中显示的简单函数,它适用于其他有条件的人BiPredicate

1 个答案:

答案 0 :(得分:2)

请注意,在(T t, U u) -> test(t, u) || other.test(t, u);中,test()方法位于IOBiPredicate上(因此被指定为throws IOException),而other.test()正在调用IOBiPredicate.or() ,但没有。这就是为什么只有lambda的前半部分导致编译错误。

由于throws IOException方法未指定test(),因此您在调用IOException时会收到错误,因为它可能会抛出throws IOException

您应该将or()添加到other,并可能使IOBiPredicate成为BiPredicate,而不是BiPredicate。通过将方法引用IOBiPredicate传递给期望bipred::test的方法,具有IOBiPredicate的来电者始终可以将其转换为BiPredicate

根本问题是您似乎在混合IOBiPredicateIOBiPredicate(也许您使BiPredicate扩展IOBiPredicate?),但它们不能安全地互换。您无法将BiPredicate实例传递到采用IOBiPredicate的方法,因为IOException会抛出BiPredicate,而Socket. Available将无法处理哪些代码。这是违反BiPredicate.test()的一个例子。