有没有办法在不添加throws声明的情况下抛出异常?

时间:2010-12-23 14:24:05

标签: java exception-handling

我有以下情况。

我有一个Java类,它继承自另一个基类并覆盖一个方法。 基本方法不会抛出异常,因此没有throws ...声明。

现在我自己的方法应该能够抛出异常,但我要么选择

  • 吞下例外
  • 添加投掷声明

两者都不满意,因为第一个会默默地忽略异常(好吧我可以执行一些日志记录),第二个会因为方法标题不同而产生编译器错误。

public class ChildClass extends BaseClass {

        @Override 
        public void SomeMethod() {
            throw new Exception("Something went wrong");
        }
}

10 个答案:

答案 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)

为什么不抛出未经检查的异常?这不必声明。

有两种选择

  • 使用未经检查的异常包装已检查的异常。
  • 不要让编译器知道您正在抛出一个已检查的异常,例如Thread.currentThread()停止(E);
  • 在Java 6中,如果异常是final并且编译器知道您可能捕获的已检查异常,则可以重新抛出异常。
  • 在Java 7中,如果异常是最终的,您可以重新抛出异常,即您不在代码中更改它。

当你在代码中抛出一个检查异常并在你的调用代码中捕获它时,后者会更有用,但是中间的层对异常一无所知。

答案 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进行异常抛出代码并在那里处理