当我没有捕捉到预期的异常类型时,为什么 IntelliJ 会显示编译错误?

Why does IntelliJ show a compilation error when I don't catch an expected exception type?

在 IntelliJ 中,我正在编写一些从 Google Cloud DataStore 检索实体的代码,使用 try catch 块,如下所示:

    try {
        T dataAccessObject = class.newInstance();
        entity = datastore.get(KeyFactory.createKey(dataAccessObject.GetEntityName().toString(), id));
        dataModel = (T)dataAccessObject.ToModel(entity);

        return dataModel;
    } catch (EntityNotFoundException e) {
    } catch (InstantiationException e) {

    } catch (IllegalAccessException e) {            

    }

对我来说,EntityNotFoundException 的空 catch 语句是一种代码味道,我宁愿删除它并允许抛出异常。

然而,当我删除该 catch 语句时,它会导致编译器错误,而且我没有看到任何关于为什么删除该语句无效的解释或理由。

datastore.get 正在调用实现 com.google.appengine.api.datastore.DatastoreService 接口的东西,这意味着可能会抛出 EntityNotFoundException ,如果我们查看构造函数可以看出接口中定义:

com.google.appengine.api.datastore.DatastoreService

public interface DatastoreService extends BaseDatastoreService {
    Entity get(Key var1) throws EntityNotFoundException;

为什么我 需要 捕获异常?为什么会出现编译错误?

Java 有两种不同的异常:checkedunchecked.

  • 检查异常:

    • 不从 java.lang.Errorjava.lang.RuntimeException 扩展的任何 java.lang.Throwable
    • 必须在可以抛出的地方明确处理。不这样做会导致编译错误。如果已检查异常在 try-catch 块中被捕获,或者如果包含方法声明为 throws 已检查异常,则会处理已检查异常。
  • 未经检查的异常:

    • java.lang.Errorjava.lang.RuntimeException 的任何实例。
    • 可以被捕获和处理,但没有必要。也可以用在方法签名的 throws 子句中,但这样做通常被认为是不好的做法。如果有人想记录方法抛出未经检查的异常的可能性,他们应该在 Javadoc 中通过 @throws.
    • 进行记录

基于编译错误,我只能假设 EntityNotFoundException 是一个 checked 异常,因此必须进行处理。有关详细信息,请参阅 Java: checked vs unchecked exception explanation


我同意空的 catch 块很臭。至少,您应该记录异常。如果你最终对每个可能的异常做同样的事情,你可以像这样重写 try-catch:

try {
    /* Do stuff... */
} catch (EntityNotFoundException | IntantiationException | IllegalAccessException ex) {
    // log ex...
}

以上语法需要 Java 7+,我相信。