如何不抛出一般指定的异常?

Gho*_*ica 21 java generics exception type-conversion throwable

我创建了一个"生成器"接口(用于方法引用,分别用于单元测试的模拟):

@FunctionalInterface
public interface Factory<R, T, X extends Throwable> {
    public R newInstanceFor(T t) throws X;
}
Run Code Online (Sandbox Code Playgroud)

我创建的那样,因为我的第一个用例实际上必须抛出一些检查WhateverException.

但是我的第二个用例没有投掷X.

我能想出的让编译器满意的最好方法是:

Factory<SomeResultClass, SomeParameterClass, RuntimeException> factory;
Run Code Online (Sandbox Code Playgroud)

这编译,并做我需要的,但仍然是丑陋的.有没有办法保留单个接口,但在声明特定实例时不提供X?

Leo*_*Aso 12

你不能用Java做到这一点.唯一的方法是创建一个子接口.

public interface DefaultExceptionFactory<R, T>
        extends Factory<R, T, RuntimeException>
Run Code Online (Sandbox Code Playgroud)


Eug*_*ene 12

唯一的方法是继承 - 但我打赌你知道这一点.为了使我的论证更加强大,请看看BinaryOperator它的延伸BiFunction.


M. *_*rov 5

这更像是一个"社会工程"的答案:我们在lambda表单上放置一个不会抛出任何东西的契约:

public interface Factory<T, R, X> {

    public R newInstanceFor(T arg) throws X;

    public static Factory<R, U, AssertionError> neverThrows(Factory<U, V, ?> input) {
        return u -> {
            try {
                return input.newInstanceFor(u);
            }
            catch(Throwable t) {
                throw new AssertionError("Broken contract: exception thrown", t);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

用法是这样的,或类似的东西:

class MyClass {
    Factory<MyInput, MyOtherClass, AssertionError> factory;

    MyClass(Factory<MyInput, MyOtherClass, ?> factory) {
        this.factory = Factory.neverThrows(factory);
    }

    public void do() {
      factory.newInstanceFor(new MyInput()).do();
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点:您无法在类型签名中真正指定合同,合同就是实施细节.如果您想在类型签名中使用它,则需要第二个子接口.