【Java基础19_1】异常Exception

来源:互联网 发布:网游编程课程 编辑:程序博客网 时间:2024/05/17 22:43

概述

  • 异常就是程序运行过程中可能产生的问题。

异常继承体系

异常继承体系图解

异常的分类

  1. 严重性问题:用错误Error类表示(一般不解决也没有能力解决)
  2. 非严重性问题:(用异常类Exception表示)
    ①. 运行期异常:发生在程序运行过程中产生的问题,只要是RunTimeException或者RunTimeException的子类都是运行时产生的异常。
    ②. 编译期异常:发生在程序编译时期产生的问题。除了RunTimeException都是编译期的异常,就是Exception的子类。
    将以上类的共性向上抽取即有了Throwable父类。

编译期异常和运行期异常的区别

  • 运行期异常如果没有处理,程序是==可以执行==。
  • 编译期异常如果没有处理,程序是==不能执行==的。

JVM会对异常的处理

  1. 当产生异常后,JVM在进行处理的时候,首先会==停止程序==,直接结束JVM,因此有异常的语句的后面的代码都不会执行
  2. 将错误信息打印到控制台。

    • 由于JVM会停止整个程序,有时我们可能会需要让程序继续往下执行,显然JVM的操作不太符合需求。因此我们有时需要人为自定义异常的处理,这样一来异常处理后,代码就能继续往下执行。

Throwable的几个常见方法

方法名 作用 String getMessage ( ) 获取异常信息 String toString ( ) 获取异常类名和异常信息 void printStackTrace ( ) 获取异常类名和异常信息,以及异常出现在程序中的位置


  • Exception作为Throwable的子类,也继承了同样的方法

异常处理的方式

  1. 使用try…catch…finally语句 处理异常
//try...catch完整格式    try{        //有可能发生异常的语句    }catch(异常类型 变量名){        //异常处理方式    }finally{        //始终要执行的代码,可以做一些收尾的工作,可省略    }
  • 注意
    • try中的代码越少越好
    • catch要做处理,哪怕是一条输出语句也可以。( 不能将异常信息隐藏 )

1.第一种格式:针对单个异常的处理方式

try{    //有可能发生异常的语句    }catch(异常类型 变量名){    //异常处理方式    }
public class ExceptionDemo {public static void main(String[] args) {    // 使用try...catch语句对异常进行一个处理    int a = 4;    int b = 0;    try{        // 可能产生问题的代码        System.out.println(a/b);        System.out.println("hello");    }catch(ArithmeticException e) {        // 对异常的处理方式        System.out.println("我捕获到了异常了。。。。");    }    System.out.println("world");}}

2. 第二种格式: 针对多个异常的处理方式。

try{ //可能产生问题的代码}catch(异常类型1 变量名) {  //对异常类型1的处理}catch(异常类型2 变量名) {  //对异常类型2的处理}catch(异常类型3 变量名) {  //对异常类型3的处理}....
  • 注意事项
    • 能明确的尽量明确到具体异常,不要轻易用相对当前异常较上级的父类异常来处理。
    • 平级关系的异常谁前谁后无所谓,如果出现了==父子关系==,==父异常必须在后面。==
//针对多个异常的处理方式public class ExceptionDemo {public static void main(String[] args) {int a = 4;int b = 1;int[] arr = {1,2,3,4,5};try {    System.out.println(a/b);    System.out.println(arr[2]);    arr = null;    System.out.println(arr[3]);}catch (ArrayIndexOutOfBoundsException e) {    System.out.println("数组角标越界啦....");} catch (ArithmeticException e) {    System.out.println("除数为0了....");} catch (Exception e) {    System.out.println("产生了异常了.....");}System.out.println("over");}}

3. JDK1.7的新特性:对多个异常的处理的简化形式

格式:try{//可能产生异常的代码}catch(异常类型1 | 异常类型2 | 异常类型3 | ...   变量名) {}注意事项:   1.处理方式是一致的。(实际开发中,好多时候可能就是针对同类型的问题,给出同一个处理)2.多个异常间必须是平级关系。
//对多个异常的处理的简化形式public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;int[] arr = {};try{    // System.out.println(a/b);    System.out.println(arr[9]);    arr = null;    System.out.println(arr[2]);}catch(ArithmeticException | ArrayIndexOutOfBoundsException | NullPointerException e){    System.out.println("产出异常了。。。。");}System.out.println("over");}}
throws的方式处理异常 (理解)
  • 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。
  • throws表示的意思是:在该方法上声明出一个异常,表示该方法在调用的时候有可能产生该种异常。
    语法:
public void add() throws 异常类型1,异常类型2..{}
  • 如果上级或者所有的上级调用都没有处理该异常,异常会层级往上抛直到JVM处理异常,即停止整个程序。

throw的概述以及和throws的区别

  1. throws:关键字,用在方法的声明上,用来表示该方法被调用的时候有可能会产生某些异常。格式:
throws 异常类型1 , 异常类型2 ,... {}
  1. throw关键字,用来在程序内部(方法中)抛出一个异常。表示的意思是实实在在的产生了一个异常,并抛出去。格式:
throw 异常对象; 
public class ExceptionDemo {public static void main(String[] args) {//try {//      show(4, 0);//} catch (Exception e) {//  System.out.println("产生异常了。。。。");//}   try {    show(4,0);   } catch (Exception e) {    System.out.println("产生异常了。。。。");   }    System.out.println("over....");}public static void show(int a ,int b) throws ArithmeticException{    if(b == 0) {        // 如果b==0,那么执行a/b肯定会抛出一个异常        // 手动的向外面抛出一个异常。//          try {//              throw new ArithmeticException("除数为0了");//          } catch (Exception e) {//              System.out.println("产生异常了。。。。");//          }        throw new ArithmeticException("除数为0了");    } else {        System.out.println(a/b);    }}}

finally关键字

  1. 特点

    • 被finally控制的语句体不管有没有异常抛出最终都会执行
    • 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0)),则finally才不会执行。
  2. 作用

    • 用于释放资源,在IO流操作和数据库操作中会见到

有关finally的面试题

  1. final, finallyfinalize的区别?

    • 答:
    • final是一个修饰符,修饰类,方法,变量。
      • 修饰的,不能被继承**
      • 修饰的方法,不能被子类重写
      • 修饰的变量,本质上是一个常量
      • final如果修饰的是引用数据类型,指的对象的地址值不能发生改变;如果修饰的是基本数据类型,指的是基本数据类型的值不能发生改变
    • finally:是一个关键字,用在try…catch语句中
      • 特点:始终都会被执行
      • 作用:做一些收尾的工作,比如释放资源,释放数据库链接
        • finalize:是Object类中的一个方法,跟垃圾回收有关。当对象变成垃圾的时候,如果垃圾回收器正在回收这个对象,那么会调用该对象的finalize(); 相当于C++中的析构函数的作用。
  2. 如果catch里面有return语句,请问finally的代码还会执行吗? 如果会,请问是在return前还是return后。

    • 答:会,在return之前执行。
  3. try…catch…finally的多种格式变形

    • try { } catch () { }
    • try { } catch ( ) { } finally { }
    • try { } finally { }

自定义异常

  • 自定义异常必须做到以下两点之一:

    1. 继承自Exception
    2. 继承自RuntimeException】
  • 查看完整Demo

/** * 分数不合法的异常类 * */public class ScoreInvalidateException extends RuntimeException{public ScoreInvalidateException() {super();}public ScoreInvalidateException(String message) {super(message);}

自定义异常小练习

  • 需求:从银行取钱,发现钱不够,给出提示。
  • 查看参考答案

注意事项 ( 针对编译期异常 ) ( 了解 )

  1. 子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类,子类的方法也可以不抛出异常。(父亲坏了,儿子不能比父亲更坏)
  2. 如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
  3. 如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws(多线程会出现这个情况)

如何使用异常处理(了解)

  • 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
  • 区别:
    • 后续程序需要继续运行就try
    • 后续程序不需要继续运行就throws