首页 > 解决方案 > 当我没有捕获预期的异常类型时,为什么 IntelliJ 会显示编译错误?

问题描述

在 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) {            

    }

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

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

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

com.google.appengine.api.datastore.DatastoreService

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

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

标签: javaexceptionintellij-ideagoogle-cloud-datastore

解决方案


Java 有两种不同的异常:checkedunchecked

  • 检查异常:

    • 任何java.lang.Throwable不从java.lang.Error或延伸的东西java.lang.RuntimeException
    • 必须在可以抛出它们的地方显式处理。不这样做会导致编译错误。如果在 try-catch 块中捕获了已检查的异常,或者将包含方法声明为throws已检查的异常,则会处理已检查的异常。
  • 未经检查的异常:

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

基于编译错误,我只能假设EntityNotFoundException是一个检查异常,因此必须处理。有关详细信息,请参阅Java:已检查与未检查的异常说明


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

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

我相信上面的语法需要Java 7+。


推荐阅读