我有以下情况。
我有一个Java类,它继承自另一个基类并覆盖一个方法。
基本方法不会抛出异常,因此没有throws ...
声明。
现在我自己的方法应该能够抛出异常,但我要么选择
两者都不满意,因为第一个会默默地忽略异常(好吧我可以执行一些日志记录),第二个会因为方法标题不同而产生编译器错误。
public class ChildClass extends BaseClass {
@Override
public void SomeMethod() {
throw new Exception("Something went wrong");
}
}
答案 0 :(得分:89)
如果你真的想要,你可以抛出未经检查的异常,而不必声明它们。未经检查的异常会延长RuntimeException
。扩展Error
的Throwable也未经检查,但只应用于非常严重的问题(例如无效的字节码)。
作为一个具体案例,Java 8添加UncheckedIOException
用于包装和重新抛出IOException
。
答案 1 :(得分:37)
这是一个技巧:
class Utils
{
@SuppressWarnings("unchecked")
private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T
{
throw (T) exception;
}
public static void throwException(Throwable exception)
{
Utils.<RuntimeException>throwException(exception, null);
}
}
public class Test
{
public static void main(String[] args)
{
Utils.throwException(new Exception("This is an exception!"));
}
}
答案 2 :(得分:24)
第三个选项是选择退出异常检查(就像标准API本身有时必须做的那样)并将检查的异常包装在RuntimeException
中:
throw new RuntimeException(originalException);
您可能希望使用更具体的RuntimeException
子类。
答案 3 :(得分:8)
我只想添加一个替代答案,纯粹是 FYI :
是的,有一种方法可以在不添加throws
声明的情况下使用sun.misc.Unsafe
类抛出已检查的异常。这在以下博客文章中描述:
Throw a checked exception from a method without declaring it
示例代码:
public void someMethod() {
//throw a checked exception without adding a "throws"
getUnsafe().throwException(new IOException());
}
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);
}
}
但是,不建议这样做。最好包装一个未经检查的异常,如其他一些答案所述。
答案 4 :(得分:4)
为什么不抛出未经检查的异常?这不必声明。
有两种选择
final
并且编译器知道您可能捕获的已检查异常,则可以重新抛出异常。当你在代码中抛出一个检查异常并在你的调用代码中捕获它时,后者会更有用,但是中间的层对异常一无所知。
答案 5 :(得分:2)
是的,有一个原因,但不建议你可以使用:
Java不安全包
getUnsafe().throwException(new IOException());
此方法抛出已检查的异常,但您的代码不会被强制捕获或重新抛出它。就像运行时异常一样。
答案 6 :(得分:2)
如果您使用 Project lombok 并且想在没有 throws
声明的情况下抛出已检查的异常,您可以将 @SneakyThrows
添加到方法中:
public void yourCaller(){
yourMethod();
}
@SneakyThrows
public void yourMethod(){
throw new Exception("Something went wrong");
}
这可以在调用者不需要捕获它们的情况下抛出已检查的异常。
Lombok 提供了在编译时修改代码的 annotation processor。使用 @SneakyThrows
,它捕获并重新抛出没有 throws
声明的异常。
如 the description of @SneakyThrows
中所述,它将代码转换为类似的内容:
public void yourMethod() {
try {
throw new Exception("Something went wrong");
} catch (Exception t) {
throw Lombok.sneakyThrow(t);
}
}
来自the sources of Lombok.sneakyThrow()
:
public static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
return Lombok.<RuntimeException>sneakyThrow0(t);
}
@SuppressWarnings("unchecked")
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
throw (T)t;
}
如您所见,它使用泛型来诱使 Java 认为这将是未经检查的异常,如 this answer 所示。
答案 7 :(得分:1)
以下是拦截已检查异常并将其包装在未经检查的异常中的示例:
public void someMethod() {
try {
doEvil();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
答案 8 :(得分:0)
您可以在方法覆盖的try-catch块中捕获异常。 那么你不需要声明throws-陈述。
答案 9 :(得分:0)
您可以使用从RuntimeException或RuntimeException本身派生的任何异常
或
使用try-block进行异常抛出代码并在那里处理