【Java基础】Java异常体系

在使用JdbcTemplate中queryForObject方法的时候抛出一个异常:

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

  queryForObject的内部逻辑是这样的:使用queryForObject时,会查询一个结果,当查询中结果多余一个或者没有都会抛出一个异常IncorrectResultSizeDataAccessException。这个向外抛出的异常为什么不需要我使用try-catch处理或者继续向外抛出呢?下面的图片展示这个异常的继承结构。
【Java基础】Java异常体系_第1张图片

Google之后认识到所有运行时异常都可以不向外抛出。为了更加快速的解决问题,决定对Java异常进行更深入的学习。

Java异常体系

【Java基础】Java异常体系_第2张图片
  首先,Throwable标志这是一个异常。
  其次,Throwable有两个子类分别是Error和Exception,Error表示的是JVM发生的异常,如内存溢出,这是应用自身程序本身无法处理的异常;而Exception则表示应用程序自身可以处理的异常。
  最后,Exception的子类分为两类,一个是RuntimeException,另外就是其他继承自Exception的异常,如IOException。区分这两类异常主要特性是是否受检。

什么是受检异常,什么是非受检异常?
  本质上,受检异常指的是会受到Java 编译器检测的异常,也就是说当你的一个方法中有抛出一个受检异常时,
你必须对它进行处理,使用try-catch或者向上抛出进行处理。非受检异常指的是不会受到Java编译器检测的异常,
当你的一个方法中抛出了非受检异常时,你不需要进行处理。
 
 Java意图上使用非受检异常来表示由于软件开发人员导致的错误,如NullPointerException;而使用
受检异常来表示一些用户误操作的错误,如IOException。“The Java Tutorial”告诉我们通常情况下我们
应该抛出受检异常,而不要抛出非受检异常。

  想一想,如果是来自外部的数据有错误,我们可以抛出异常来说明用户传入的参数有错误;而如果是开发人员导致的
错误,且我们开发人员自己都知道自己的代码有异常,那直接改正不久好了,干嘛还要向外抛出呢!所以通常是不会
继承非受检异常的。

  运行时异常虽然可以不进行处理,但是可能导致线程终止或者应用终止。如果是非主线程,则由Thread.run()抛出异常后,线程终止。如果是主线程(即main方法)抛出异常,则应用终止。

有兴趣可以将下面的代码复制到编译器中来检测受检异常和非受检异常。

public class Main {
    public void caller() {
        callee();
    }

    public void callee() throws Exception{
        throw new Exception();
    }
}

上面的代码中在调用callee方法的时候将编译不过。

public class Main {
    public void caller() {
        callee();
    }

    public void callee(){
        throw new RuntimeException();
    }
}

上面的代码将不会有任何告警。

参考:
Java 的 Checked 和 Unchecked Exception【译】

你可能感兴趣的:(java,exception)