Reg*_*kie 67 java android runnable throws
我在实现Runnable的类中调用run()的方法被设计为抛出异常.
但Java编译器不会让我这样做,并建议我用try/catch包围它.
问题是,通过try/catch包围它,我使特定的 run()无用.我确实想抛出那个例外.
如果我throws为run()本身指定,编译器会抱怨Exception is not compatible with throws clause in Runnable.run().
通常我完全没有让 run()抛出异常.但我有独特的情况,我必须具备该功能.
如何解决这个限制?
Ale*_*tin 72
您可以使用a Callable,将其提交给a ExecutorService并等待结果 FutureTask.isDone()返回ExecutorService.submit().
当isDone()返回true时,你打电话FutureTask.get().现在,如果你Callable已经抛出了一个wiill ,Exception那么你将可以使用原始的Exception .FutureTask.get()ExceptionException.getCause()
Ern*_*ill 20
如果run()抛出一个已检查的异常,会有什么结果呢?run()由于您没有编写调用它的代码,因此无法将该调用封装在处理程序中.
您可以在run()方法中捕获已检查的异常,并RuntimeException在其位置抛出未检查的异常(即).这将使用堆栈跟踪终止线程; 也许这就是你所追求的.
如果你希望你的run()方法在某个地方报告错误,那么你可以只为run()方法的catch块提供一个回调方法来调用; 该方法可以在某处存储异常对象,然后您感兴趣的线程可以在该位置找到该对象.
Ale*_*yak 18
如果你想传递一个实现类Runnable为Thread框架,那么你必须通过该框架的规则玩,看欧内斯特·弗里德曼-希尔的回答,为什么这样做,否则是一个坏主意.
不过,我有一种预感,你想run直接在你的代码中调用方法,所以你的调用代码可以处理异常.
这个问题的答案很简单.不要使用Runnable来自线程库的接口,而是使用修改后的签名创建自己的接口,该签名允许抛出已检查的异常,例如
public interface MyRunnable
{
void myRun ( ) throws MyException;
}
Run Code Online (Sandbox Code Playgroud)
您甚至可以创建一个适配器,将该接口转换为真实的Runnable(通过处理已检查的异常),适用于Thread框架.
eri*_*son 16
是的,有一种方法可以从方法中抛出一个已检查的异常run(),但它太可怕了,我不会分享它.
这是你可以做的事情; 它使用与运行时异常相同的机制:
@Override
public void run() {
try {
/* Do your thing. */
...
} catch (Exception ex) {
Thread t = Thread.currentThread();
t.getUncaughtExceptionHandler().uncaughtException(t, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,如果你的run()方法确实是a的目标Thread,那么抛出异常是没有意义的,因为它是不可观察的; 抛出异常与不抛出异常(无)具有相同的效果.
如果它不是Thread目标,请不要使用Runnable.例如,也许Callable更合适.
有些人试图说服您必须遵守规则。听着,但听不听,你要根据自己的情况自行决定。现实是“你应该遵守规则”(而不是“你必须遵守规则”)。请注意,如果您不遵守规则,可能会产生后果。
这种情况不仅适用于RunnableJava 8 的情况,而且在 Streams 和其他引入函数式接口而无法处理检查异常的地方也经常出现。例如,Consumer、Supplier、Function等都BiFunction被声明为没有处理检查异常的设施。
那么有哪些情况和选择呢?在下面的文本中,Runnable代表任何不声明异常的功能接口,或者声明的异常对于当前的用例来说过于有限。
Runnable,并且可以Runnable用其他东西替换。
Runnable为Callable<Void>. 基本上是一样的,但是允许抛出异常;return null最后不得不这样做,这是一个轻微的烦恼。Runnable用您自己的自定义替换@FunctionalInterface,该自定义可以准确地抛出您想要的异常。Callable<Void>使用Runnable.RuntimeException.您可以尝试以下操作。这有点像黑客,但有时我们需要黑客。因为,是否应该检查或不检查异常是由其类型定义的,但实际上应该根据情况来定义。
@FunctionalInterface
public interface ThrowingRunnable extends Runnable {
@Override
default void run() {
try {
tryRun();
} catch (final Throwable t) {
throwUnchecked(t);
}
}
private static <E extends RuntimeException> void throwUnchecked(Throwable t) {
throw (E) t;
}
void tryRun() throws Throwable;
}
Run Code Online (Sandbox Code Playgroud)
我更喜欢这个,new RuntimeException(t)因为它的堆栈跟踪更短。
您现在可以执行以下操作:
executorService.submit((ThrowingRunnable) () -> {throw new Exception()});
Run Code Online (Sandbox Code Playgroud)
免责声明:当泛型类型信息不仅在编译时处理,而且在运行时处理时,以这种方式执行未经检查的强制转换的能力实际上可能会在 Java 的未来版本中被删除。
@FunctionalInterface
public interface CheckedRunnable<E extends Exception> extends Runnable {
@Override
default void run() throws RuntimeException {
try {
runThrows();
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
void runThrows() throws E;
}
Run Code Online (Sandbox Code Playgroud)