java 为什么 Runnable 的 run() 不能抛出已检查的异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11410042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why cannot run() of Runnable throw checked Exceptions?
提问by Inquisitive
According to section 6.3.2 of JCIP:
Runnable is a fairly limiting abstraction; run can not return a value or throw checked exception .
Runnable 是一个相当有限的抽象;运行不能返回值或抛出检查异常。
run()
can not return a value since its return type is void but why can not it throw a checked exception ?
run()
不能返回一个值,因为它的返回类型是 void 但为什么不能抛出一个已检查的异常?
回答by Peter Lawrey
It cannot throw a checked exception because it wasn't declared as throwing a checked exception from the first version and it is too dangerous to change it.
它不能抛出已检查的异常,因为它没有被声明为从第一个版本抛出已检查的异常,并且更改它太危险了。
Originally Runnable
was only used in a wrapped Thread
, and it was assumed the developer would want to catch all checked exceptions and handle them rather than logging them to System.err
.
最初Runnable
仅用于包装Thread
,并且假定开发人员希望捕获所有已检查的异常并处理它们而不是将它们记录到System.err
.
Callable
was added when you can add individual tasks to an Executor
where you can capture the result in a Future
and any exception thrown.
Callable
当您可以将单个任务添加到Executor
您可以在 a 中捕获结果Future
和抛出的任何异常时添加。
Callable
now allows you to return a value and optional declare a checked exception.
Callable
现在允许您返回一个值并可选地声明一个已检查的异常。
BTW: One way you can say you don't want a return or throw a checked exception from a callable is to use something like
顺便说一句:您可以说您不想从可调用对象返回或抛出已检查异常的一种方法是使用类似的方法
Callable<Void> callable = new Callable<Void>() {
public Void call() {
// do something
return null;
}
};
回答by Tom Anderson
This is not an answer to the question. Rather, it is a followup to Lukas Eder's answer, showing another way to smuggle a checked exception into a place where it is not statically allowed. This relies on the fact that if a no-argument constructor is invoked with newInstance
, any checked exception it throws escapes upward.
这不是问题的答案。相反,它是Lukas Eder 的回答的后续,展示了另一种将已检查异常走私到静态不允许的地方的方法。这依赖于这样一个事实:如果使用 调用无参数构造函数,则newInstance
它抛出的任何已检查异常都会向上转义。
public class Thrower {
private static final ThreadLocal<Exception> toThrow = new ThreadLocal<Exception>();
public static void throwUnsafely(Exception e) {
try {
toThrow.set(e);
Thrower.class.newInstance();
} catch (InstantiationException f) {
throw new RuntimeException("unexpected exception while throwing expected exception", f);
} catch (IllegalAccessException f) {
throw new RuntimeException("unexpected exception while throwing expected exception", f);
} finally {
toThrow.remove();
}
}
private Thrower() throws Exception {
throw toThrow.get();
}
}
This is class-A truly ancient black hat Java voodoo. Do not ever do this. Except at parties to impress people.
这是 A 级真正古老的黑帽 Java 巫术。永远不要这样做。除了在派对上给人们留下深刻印象。
回答by Tom Anderson
run()
can't throw a checked exception because it is not declared to do so. You can't throw checked exceptions without declaring them.
run()
不能抛出已检查的异常,因为它没有声明这样做。你不能在不声明它们的情况下抛出已检查的异常。
You also can't declare checked exceptions on a method which overrides or implements another method which doesn't throw that exception. So, implementations of Runnable
can't simply add throws
clauses to their implementations of run()
.
您也不能在覆盖或实现不引发该异常的另一个方法的方法上声明已检查的异常。因此, 的实现Runnable
不能简单地将throws
子句添加到它们的run()
.
回答by Lukas Eder
You can always unsafely throw checked exceptions:
您总是可以不安全地抛出已检查的异常:
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeSample {
public void methodWithNoDeclaredExceptions( ) {
Unsafe unsafe = getUnsafe();
unsafe.throwException( new Exception( "this should be checked" ) );
}
private Unsafe getUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public static void main( String[] args ) {
new UnsafeSample().methodWithNoDeclaredExceptions();
}
}
See the full article here:
在此处查看全文:
http://java.dzone.com/articles/throwing-undeclared-checked.
http://java.dzone.com/articles/throwing-undeclared-checked。
Another alternative:
另一种选择:
public class Test {
public static void main(String[] args) {
doThrow(new SQLException());
}
public static void doThrow(Exception e) {
Test.<RuntimeException> doThrow0(e);
}
@SuppressWarnings("unchecked")
public static <E extends Exception> void doThrow0(Exception e) throws E {
throw (E) e;
}
}
This was shown here:
这显示在这里:
http://java.dzone.com/articles/throw-checked-exceptions
http://java.dzone.com/articles/throw-checked-exceptions
Having said so, don't do it! ;-)
说了这么多,千万别做!;-)
回答by amicngh
If you look at the Runnable Interfaceyou find that void run()
method is not declared as throwing any checked exception and your Thread class implements Runnable Interface .
如果您查看Runnable Interface,您会发现该void run()
方法未声明为引发任何已检查的异常,并且您的 Thread 类实现了 Runnable Interface 。
JLSsays that method m1 cannot throw exception if in Interface/Superclass it is not declared.
JLS说如果在接口/超类中没有声明方法 m1 不能抛出异常。
回答by lab bhattacharjee
I think the motivation behind keeping the signature void run() in Runnable is that it is not meant to be invoked like other methods, instead it is designed to be invoked by the CPU thread scheduler. If so, who is going to receive its return value and who is going to handle thrown checked exception by this. UncaughtExceptionHandlercame in Java 5.0 to handle uncaught exceptions thrown by a Thread. The Executor Framework saves the returned value or thrown exception( wrapper in ExecutionException) as the states of some Object shared across threads(like Outer class instance) and purveys those to the invoker(who is running in some other thread) of Future.get().
我认为在 Runnable 中保留签名 void run() 的动机是它不像其他方法那样被调用,而是被设计为由 CPU 线程调度程序调用。如果是这样,谁将接收其返回值,谁将处理由此引发的已检查异常。UncaughtExceptionHandler出现在 Java 5.0 中,用于处理线程抛出的未捕获异常。Executor 框架将返回值或抛出的异常(ExecutionException 中的包装器)保存为一些跨线程共享的对象的状态(如外部类实例),并将这些状态提供给 Future 的调用者(在其他线程中运行)。得到()。