[Java学习笔记] Java异常机制(也许是全网最独特视角) ...

打印 上一主题 下一主题

主题 876|帖子 876|积分 2628

Java 异常机制(也许是全网最独特视角)

一、Java中的“异常“指什么


  • 什么是异常
    一句话简单理解:异常是程序运行中的一些异常或者错误。
    (纯字面意思)
  • Error类 和 Exception类
    Java中“万物皆对象”,异常也不例外,
    Java把异常当做对象来处理,并将异常分为两大类——Error(错误)和Exception(异常),它们都是Throwable类的子类。
    这里看起来可能有点奇怪,什么叫“把异常分为错误和异常两类”??可以这样粗暴地理解——异常有两大类,一类是错误异常(Error),另一类是异常异常(Exception)
    至于为什么这么奇怪,我觉得既有翻译的问题,也有Java文档没说清楚的问题。(主要是翻译的锅)
    Oracle的JavaSE官方文档是这样说的:
    An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.
    The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch.
    所以个人见解,我们可以把Throwable这个类翻译为“事故类 ”(单词problem:问题、状况、事故),这个“事故类”的对象具有可被抛出的性质,且”事故类“Throwable有两个子类“错误事故”(Error,对应致命的大事故)和"异常事故"(Exception,对应剩余可以处理的事故)。
    所以Java的“异常机制”这个翻译很容易误导人,让人奇怪什么叫异常包括错误和异常,EXception的异常和“异常机制”的异常,这两个翻译冲突了,所以我认为更应该翻译为Java的“事故机制”。
    Error类的常见子类有IOError、AWTError、VirtualMachineError等,
    Exception类的常见子类有IOException、RuntimeException等。
  • Error和Exception的区别
    Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这类异常时,JVM一般会选择终止线程;而Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这类异常。
    个人总结:曾经纠结Error和Exception的区别纠结了好久,后来发现根本不用纠结,就当成一样的东西就好了,都是“意外状况”,只不过一个严重点一个不严重点而已。由于Error是严重的异常,对于程序已经致命了,所以并不需要捕获(catch)或者声明(throws),而Exception属于不那么严重,还可以“挽救”或者说“预判”的异常,所以可以被捕获(catch)或者声明(throws)来做出进一步处理。
二、异常的捕获和抛出


  • 异常处理的五个关键字——try、catch、finally、throw、throws。

    • try 和 catch 关键字可以捕获异常。
      try/catch 代码块放在异常可能发生的地方,try 代码块中的代码会先被执行,catch 语句包含要捕获异常类型的声明。当 try 语句中的代码发生一个异常时,try 后面的 catch 块就会被检查,如果发生的异常是catch语句所声明的异常类型的实例,则该异常会被传递到该 catch 块并执行catch代码块中的代码,类似于传递一个参数到方法中。
      finally代码块出现在catch代码块之后,无论try代码块中是否发生异常,finally代码块中的代码总会被执行。
      注意:1、try代码块后必须有catch代码块或者finally代码块;
      ​                        2、靠上的catch所声明的异常类型不能是靠下的catc所声明的异常类型的父类(如以下代码中,e1不是e2的父类)。
      1. try{
      2.     //正常执行的代码
      3. }catch(Exception1 e1){
      4.     //捕获到Exception1类的异常后执行的代码
      5.     //捕获到的异常被赋值给e1
      6. }catch(Exception2 e2){
      7.     //捕获到Exception2类的异常后执行的代码
      8.   //捕获到的异常被赋值给e2
      9. }finally{
      10.     //善后代码
      11. }
      复制代码
    • throw 和 throws 关键字用于主动抛出异常。
      两个关键字的区别是,throw用于抛出一个异常,而throws用于声明方法可能抛出的异常。
      throw只能抛出一个异常对象,throws可以声明多个可能发生的异常类。
      即一个负责抛出,一个负责声明。
      注意:1、若方法中有 异常(严格来说是检查异常,详见后文)抛出,必须使用throws语句在方法头处声明异常,或者在方法体内使用try/catch语句将异常抛出语句包围(将throw语句置于try代码块中);
      ​                        2、若一个方法使用了throws语句声明异常,则引用此方法的另一个方法必须使用throws语句在方法头处声明异常,或者使用try/catch语句将引用此方法的语句包围(将引用此方法的语句置于try代码块中)
      1. public void test1(){
      2.     //使用try/catch语句处理异常
      3.     try{
      4.         throw new Exception();
      5.     }catch(Exception e){
      6.         System.out.println("Thers's an exception.")
      7.     }
      8. }
      9. public void test2() throws Exception{
      10.     //使用throws语句在方法头处声明异常
      11.     throw new Exception();
      12. }
      13. public void test3() throws Exception{
      14.     //引用test2也要声明异常
      15.     test2();
      16. }
      17. public void test4() throws Exception{
      18.     //引用test2也要声明异常
      19.    
      复制代码
      总结:可以这样理解,throw就是抛出异常,try/catch就是处理异常,throws就是暂时不处理、交给引用自己的方法处理。

  • 检查异常(checked exception)和非检查异常(unchecked exception)
    检查异常:除了Error类及其子类 和 RuntimeException类及其子类,其它的Throwable子类都是检查异常。
    非检查异常:Error类及其子类 和 RuntimeException类及其子类。
    检查异常是编译器要求程序必须处置的异常,这种异常的特点是Java编译器会检查它是否被捕获(try/catch)或者声明(throws),否则编译不通过。非检查异常是编译器不要求强制处理的异常。
    1. public viod test(){
    2.     //抛出Error类对象但并不做处理,编译也能通过。
    3.     throw new Error();
    4. }
    5. public viod test(){
    6.     //抛出RuntimeException类对象但并不做处理,编译也能通过。
    7.     throw new RuntimeException();
    8. }
    9. //Error类及其子类 和 RuntimeException类及其子类 都是非检查异常,
    复制代码
  • 运行时异常和非运行时异常
    运行时异常:RuntimeException类及其子类。
    非运行时异常:RuntimeException以外的Exception类及其子类。
    其实运行时异常就是 除去Error类的非检查异常,
    如果我们不去处理运行时异常,JVM会接管处理,系统会把异常一直往上层抛,一直到最上层,
    最上层抛出之后,如果抛出异常在线程中,这个线程就会退出,如果抛出异常在主程序中,整个程序就退出了。
    也就是说,如果不对运行时异常进行处理,程序会通过编译并运行,出现运行时异常后,要么是线程终止,要么是主程序终止。
    1. public class Draft {
    2.     public static void test1(){
    3.         throw new RuntimeException();
    4.     }
    5.     public static void test2(){
    6.         test1();
    7.     }
    8.     public static void main(String[] args) {
    9.         test2();
    10.     }
    11. }
    复制代码
    运行以上代码,终端会出现以下结果,
    Exception in thread "main" java.lang.RuntimeException
    at Draft.test1(Draft.java:3)
    at Draft.test2(Draft.java:6)
    at Draft.main(Draft.java:9)

三、自定义异常


  • 如果Java提供的内置异常类型不能满足程序设计的需求,我们可以自定义异常类,只需要继承Exception类或者它的子类,以上异常机制对自定义的异常类同样适用。
呼,终于写完咯!人生第一篇博客,欢迎各路大佬指正!
此后会持续更新学习笔记,每一篇都会用心去写去感悟。
原创声明:本文完全为作者兰勃基尼原创,转载请声明并附上原文链接https://www.cnblogs.com/ForJoy/p/16452920.html。作者各平台用户名如下
知乎:我求知若渴呀
博客园:兰勃基尼_CodeJoy
CSDN:兰勃基尼_CodeJoy

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

风雨同行

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表