use*_*357 13 java generics exception throws checked-exceptions
一些背景,然后一些问题.
我最近才发现接口(或类)在其方法可能引发的(已检查)异常类型中可能是通用的.例如:
interface GenericRunnable<X extends Exception> {
void run() throws X;
}
Run Code Online (Sandbox Code Playgroud)
关键是如果您稍后使用,例如IOException并调用该run方法来实例化它,则编译器知道您需要捕获IOException或将其标记为抛出.更好的是,如果X是a RuntimeException,你根本不需要处理它.
这是一个使用上述界面的人为例子,但它基本上是一个回调,应该很常见.
public <X extends Exception> void runTwice(GenericRunnable<X> runnable) throws X {
runnable.run(); runnable.run();
}
...
public myMethod() throws MyException {
runTwice(myRunnable);
}
Run Code Online (Sandbox Code Playgroud)
我们正在调用一个通用的实用程序方法runTwice(可能在外部库中定义)来运行我们自己的特定方法并使用特定的检查异常,并且我们不会丢失任何有关可能抛出哪个特定的已检查异常的信息.
另一种方法将是简单地使用throws Exception双方的Runnable.run方法和runTwice方法.这不会限制Runnable接口的任何实现,但是检查异常的优点将会丢失.或者根本就没有throws,也失去了检查异常的优势,并可能迫使实现包装.
因为我从未见过throws X,也许我错过了什么.此外,我已经看到回调示例多次用作针对已检查异常的参数,而不会被反驳.(这个问题对检查异常的优缺点不感兴趣.)
是throws X通常一个好主意?优缺点都有什么?你能给出一些使用throws X或不使用但应该具有的例子吗?
基本上,我想进一步了解一下.您可以评论以下示例.
OutputStream抛出IOException(也许ByteArrayOutputStream可以延伸GenericOutputStream<RuntimeException>)
Callable/Future.get
Commons Pool borrowObject/makeObject
(自编辑以来,我并不是在回想起这些是否/应该以不同的方式进行设计.相反,它会throws X更好throws Exception.)
我一直使用这种模式,主要用于函数式 java。
优点:
您可以拥有多种高阶模式(例如 Visitor),即:
interface ExceptionalVoidVisitor< E extends Exception > {
void handleA( A a ) throws E;
void handleB( B b ) throws E;
}
interface VoidVisitor extends ExceptionalVoidVisitor< RuntimeException > {}
interface ExceptionalVisitor< T, E extends Exception > {
T handleA( A a ) throws E;
T handleB( B b ) throws E;
}
interface Visitor< T > extends ExceptionalVisitor< T, RuntimeException > {}
Run Code Online (Sandbox Code Playgroud)您的客户可以为他可能抛出的所有异常声明一个基本异常类,最终您将得到一个完全通用的库。
缺点: