【Java基础19_1】异常Exception

概述

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

异常继承体系

异常继承体系图解

异常的分类

  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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值