java-day11-异常

11.1 概述

Exception:Java程序在运行时出现的不正常情况。Java就按照面向对象的思想对不正常进行行为描述和对象的封装。

问题分两种:

  1. Error:由系统底层发生的,告诉jvm,jvm告诉使用者,不做针对性处理。解决方法:修改代码
  2. Exception:jvm发生,并告诉使用者,可以进行针对性的处理。

Throwable:定义了对于问题共性的功能。

Exception总结:

  1. 运行时发生
  2. 符合面向对象,将问题描述并封装成对象
  3. error和exception的区别。
public class test {
    public static void main(String[] args){
        int[] arr = new int[1];
        int[] arr1 = new int[1024*1024*10000000000000];//Error:过大的整数: 10000000000000
        System.out.println(arr[1]);  //抛出异常,ArrayIndexOutOfBoundsException    
    }
}

11.2 异常体系&异常发生过程

Throwable:定义了对于问题共性的功能。

public class test {
    public static void main(String[] args){
        int[] arr = new int[1];
        System.out.println(arr[1]);//ArrayIndexOutOfBoundsException
        /*
            发生问题时,jvm就将这个已知的问题封装成了对象
            throw ArrayIndexOutOfBoundsException(1);
            将问题抛给调用者调用者main函数。
            main没有针对性的处理方式。main就继续往外抛给调用者jvm,jvm就使用了默认的处理方式。
            将问题的名称+信息+位置在控制台上显示出来。让调用者看到并结束程序。
         */
    }
}

11.3 异常处理方式-throws

异常的处理有两种:

1. 遇到问题不进行具体的处理,而是继续抛给调用者。其实就是在函数上通过throws关键字声明异常。告诉调用者处理

在编写功能时,编写者知道该功能有可能发生问题。而这个问题很容易来自于调用者传递的参数。而导致功能无法运行。
这时发生的问题就应该让该调用者知道,并最好让调用者有预先的处理方式。
声明问题需要使用关键字。throws异常类,声明的目的:让调用者处理。

class Demo{

    int div(int a, int b) throws Exception{
        return a/b;//throw new ArithmeticException("/ by zero");抛给主函数里面的int num = demo.div(4,0); 这一行的调用者
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        int num = demo.div(4,0);    // 调用者
        System.out.println("num = "+num);
    }
}

2. 针对性的处理方式:捕获!

        try{

        }
        catch (异常类 变量){
            // 这是真正的捕获,处理异常的代码‘
        }
        finally {
            // 一定被执行的代码
        }

示例:

class Demo{
    int div(int a, int b) throws Exception{
        return a/b;//throw new ArithmeticException("/ by zero");抛给主函数里面的int num = demo.div(4,0); 这一行的调用者
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        try{
            int num = demo.div(4,0); // 调用者
            System.out.println("num = "+num);
        }
        catch (Exception e){
            // 这是真正的捕获,处理异常的代码
            System.out.println("异常啦");
        }
        System.out.println("over");

    }
}

输出:

异常啦
over

11.4 异常常见方法&throw

class Demo{
    int div(int a, int b) throws Exception{
        return a/b;//throw new ArithmeticException("/ by zero");抛给主函数里面的int num = demo.div(4,0); 这一行的调用者
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        try{
            int num = demo.div(4,0); // 调用者
            System.out.println("num = "+num);
        }
        catch (Exception e){  //Exception e = new ArithmeticException("/ by zero");
            // 这是真正的捕获,处理异常的代码
            System.out.println("异常啦");
            System.out.println(e.getMessage());//异常信息
            System.out.println(e.toString());//异常名+异常信息
            e.printStackTrace();//名字+位置+信息 jvm默认处理收到异常就是调用这个方法。将信息显示在屏幕上
        }
        System.out.println("over");

    }
}

输出

异常啦
java.lang.ArithmeticException: / by zero
/ by zero
	at day11.Demo.div(test.java:5)
java.lang.ArithmeticException: / by zero
	at day11.test.main(test.java:13)
over

throws 声明异常;
throw 抛出异常。

class Demo{
    int div(int a, int b) throws Exception{  //throws 声明异常
        if(b==0){
            throw new ArithmeticException("不能除以0哦");//throw 抛出异常,自定义异常信息
        }
        return a/b;//throw new ArithmeticException("/ by zero");抛给主函数里面的int num = demo.div(4,0); 这一行的调用者
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        try{
            int num = demo.div(4,0); // 调用者
            System.out.println("num = "+num);
        }
        catch (Exception e){  //Exception e = new ArithmeticException("/ by zero");
            // 这是真正的捕获,处理异常的代码
            System.out.println("异常啦");
            System.out.println(e.getMessage());//异常信息
            /*System.out.println(e.toString());//异常名+异常信息
            e.printStackTrace();//名字+位置+信息 jvm默认处理收到异常就是调用这个方法。将信息显示在屏幕上
            */
        }
        System.out.println("over");

    }
}

输出

异常啦
不能除以0哦
over

11.5 throw和throws的区别

throw和throws有什么区别?

  • 位置不同。
    throws 用在函数上,后面跟的是异常类,可以跟多个
    throw 用在函数内,后面跟的是异常对象。
  • 功能不同。
    throws 用来声明异常,让调用者只知道有可能出现的问题,并由调用者可以给出预先的处理方式。
    throw 抛出具体问题对象。执行到throw功能就已经结束了,跳转到调用者。并将具体的问题对象也抛给调用者。也就是说throw语句独立存在时,下面不要定义其他语句。因为执行不到。

异常体系的特殊情况:
Exception:

  • Error
  • Exception

异常体系最大的特点就是体系中的类以及类产生的对象,都具备可抛性,可抛性的意思是可以被throw和throws所操作。

11.6 异常处理原则&运行时异常

异常的原则:

1. 功能内部有异常throw抛出,功能上一定要throws声明。内部抛什么,功能上就声明什么。声明的目的就是为了让调用者处理,如果调用者不出处理,编译失败。

class Demo{
    int div(int a, int b) // 这里应该加上throws Exception
    { 
        if(b==0){
            throw new ArithmeticException("不能除以0哦");
        }
        return a/b;
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        int num = demo.div(4,0); // 调用者 ,这里应该要处理异常
        System.out.println("num = "+num);
        System.out.println("over");

    }
}

输出:

Error:(15, 27) java: 未报告的异常错误java.lang.Exception; 必须对其进行捕获或声明以便抛出

修改后的代码:

class Demo{
    int div(int a, int b) throws Exception{
        if(b==0){
            throw new Exception("不能除以0哦");
        }
        return a/b;
    }
}

public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        try{
            int num = demo.div(4,0); // 调用者
            System.out.println("num = "+num);
        }catch (Exception e){
            System.out.println(e.toString());
        }
        System.out.println("over");

    }
}

输出:

java.lang.Exception: 不能除以0哦
over

2.特殊情况:当函数内通过throw抛出了RuntimeException及其子类的异常对象时,函数上可以不用throws声明。不声明的目的就是不让调用者处理。让调用者的程序停止,要对代码进行修改。

Exception分两种:

  1. 编译时,会被检测的异常
  2. 运行时异常(编译是不检测) RuntimeException

11.7 异常的应用

public class test {
    public static void main(String[] args){
    
        int[] arr = new int[2];
        System.out.println("element:"+getElement(arr,3));

    }

    //定义一个功能,返回一个整型数组中指定位置的元素
    public static int getElement(int[] arr, int index){
        if(arr == null){
            throw new NullPointerException("数组实体不存在");
        }
        if(index<0||index>arr.length){
            throw new ArrayIndexOutOfBoundsException(index+",角标不存在");
        }
        // NullPointerException和ArrayIndexOutOfBoundsException都属于RuntimeException的子类
        int element = arr[index];
        return element;
    }
}

11.8 自定义异常

在自定义的程序中,如果有了问题,也可以像Java中的异常一样,对问题进行描述。

举例:
定义一个功能可以实现除法运算,但是除法不可以为负数。

//将负数为除数的问题描述
class FushuException extends RuntimeException{
    FushuException(){
        super();
    }
    FushuException(String message){
        super(message);//父类已经处理了信息,子类只需要把信息传给父类即可
    }
}
class Demo{
    int div(int a, int b)
    {

        if(b<0){
            throw new FushuException("负数不可以作为整数");
        }
        if(b==0){
            throw new ArithmeticException("不能除以0哦");
        }
        return a/b;
    }
}



public class test {
    public static void main(String[] args){
        Demo demo = new Demo();
        try{
            int num = demo.div(4,-1); // 调用者
            System.out.println("num = "+num);
        }catch (Exception e){
            System.out.println(e.toString());
        }
        System.out.println("over");

    }
}

11.9 异常练习

小结
异常:其实就将问题封装成对象,并抛给调用者。

1.如果声明了,就需要调用者处理(继续声明 or 捕获)

什么时候声明?什么时候捕获?

  • 功能内部可以解决,就捕获
  • 不能解决,或者解决了还必须告诉调用者问题,这时就应该声明。

举例:
毕老师用电脑上课。

class Computer{
    public void run(){
        System.out.println("电脑运行");
    }
}
class Teacher{
    private String name;
    private Computer comp;
    Teacher(String name){
        name = this.name;
        comp = new Computer();
    }

    //讲课
    public void prelect(){
        comp.run();
    }
}
public class test {
    public static void main(String[] args){

        Teacher teacher = new Teacher("毕老师");
        teacher.prelect();

    }
}

上课过程中,会发生问题:比如电脑蓝屏,电脑冒烟了,需要对问题进行描述。

//是可以处理的异常,继承Exception
class LanPingException extends Exception{
    LanPingException(){
        super();
    }
    LanPingException(String message){
        super(message);
    }
}

class MaoYanException extends Exception{

    MaoYanException(){
        super();
    }
    MaoYanException(String message){
        super(message);
    }
}

class Computer{
    private int state = 2;//0为正常状态
    public void run() throws LanPingException, MaoYanException{
        if(state == 1)
            throw new LanPingException("电脑蓝屏了");
        if(state == 2)
            throw new MaoYanException("电脑冒烟了");
        System.out.println("电脑运行");
    }

    public void reset(){
        System.out.println("电脑重启");
        state = 0;
    }
}
class Teacher{
    private String name;
    private Computer comp;
    Teacher(String name){
        this.name = name;
        comp = new Computer();
    }

    //讲课
    public void prelect() throws MaoYanException{
        try{
            comp.run();
            System.out.println("讲课");
        }
        catch (LanPingException e){
            System.out.println(e.toString());
            comp.reset();
            //继续讲课
            prelect();
        }
        catch (MaoYanException e){  //MaoYanException e = new MaoYanException();
            System.out.println(e.toString());
            exc();
            throw e;//继续抛
        }

    }
    public void exc(){
        System.out.println("同学们自己练习");
    }
}
public class test {
    public static void main(String[] args){

        Teacher teacher = new Teacher("毕老师");
        try{
            teacher.prelect();
        }
        catch (MaoYanException e){
            System.out.println("换老师");
        }
    }
}


当Computer类中的state初始化为0,时输出结果:

电脑运行
讲课

当Computer类中的state初始化为1,时输出结果:

day11.LanPingException: 电脑蓝屏了
电脑重启
电脑运行
讲课

当Computer类中的state初始化为2,时输出结果:

day11.MaoYanException: 电脑冒烟了
同学们自己练习
换老师

请注意,老师讲课的函数prelect抛出LanPingException,这是不合适的,应该进一步抽象成NoPlanException,进行异常转换,封装本层异常,对外暴露对方能处理的异常。

//是可以处理的异常,继承Exception
class LanPingException extends Exception{
    LanPingException(){
        super();
    }
    LanPingException(String message){
        super(message);
    }
}

class MaoYanException extends Exception{

    MaoYanException(){
        super();
    }
    MaoYanException(String message){
        super(message);
    }
}

//课时无法进行
class NoPlanException extends Exception{
    NoPlanException(){
        super();
    }
    NoPlanException(String message){
        super(message);
    }
}
class Computer{
    private int state = 2;//0为正常状态
    public void run()throws LanPingException, MaoYanException{
        if(state == 1)
            throw new LanPingException("电脑蓝屏了");
        if(state == 2)
            throw new MaoYanException("电脑冒烟了");
        System.out.println("电脑运行");
    }

    public void reset(){
        System.out.println("电脑重启");
        state = 0;
    }
}
class Teacher{
    private String name;
    private Computer comp;
    Teacher(String name){
        this.name = name;
        comp = new Computer();
    }

    //讲课
    public void prelect() throws NoPlanException{
        try{
            comp.run();
            System.out.println("讲课");
        }
        catch (LanPingException e){
            System.out.println(e.toString());
            comp.reset();
            //继续讲课
            prelect();
        }
        catch (MaoYanException e){  //MaoYanException e = new MaoYanException();
            System.out.println(e.toString());
            exc();
            throw new NoPlanException("课时进度停止");//继续抛,异常转换
        }

    }
    public void exc(){
        System.out.println("同学们自己练习");
    }
}
public class test {
    public static void main(String[] args){

        Teacher teacher = new Teacher("毕老师");
        try{
            teacher.prelect();
        }
        catch (NoPlanException e){
            System.out.println(e.toString());
            System.out.println("换老师");
        }


    }
}

输出结果:

day11.MaoYanException: 电脑冒烟了
同学们自己练习
day11.NoPlanException: 课时进度停止
换老师

再例子说明异常转换:封装本层异常,对外暴露对方能处理的异常。

import java.sql.SQLException;

class NoValueException extends Exception{
    NoValueException(){
        super();
    }
    NoValueException(String message){
        super(message);
    }
}

class App{
    public void show(){
        try{
            new DBTool().oprate();
        }catch (NoValueException e){ //不是直接将SQLException抛给数据库调用者,而是告诉他NoValueException

        }
    }
}
class DBTool{
    public void oprate() throws NoValueException{
        //连接数据库

        try{
            throw new SQLException();
            //数据操作throw new SQLException
        }catch (SQLException e){
            //解决了数据库异常
        }


        //关闭数据库
    }
}
public class DBTest {
}

11.10 finally代码块

try
catch
finally

finally的作用是:无论是否有异常发生,都要对资源进行释放。资源释放的动作就是在finally 代码块中的。

public class ExceptionDeom {
    public static void main(String[] args){
        try{
            int num = 4/0;
            System.out.println("num:"+num);
        }catch (Exception e){
            System.out.println(e.toString());
            return ;
            //System.exit(0); //退出jvm。只有这种情况,finally也不执行
        }finally {
            System.out.println("finally");//一定会被执行的代码
        }
        System.out.println("over");
    }
}

输出

java.lang.ArithmeticException: / by zero
finally
over

11.11 处理异常代码块组合方式(必须掌握)

try{
}
catch(){
}
finally{
}
的几种组合方式。

1. 没有资源需要释放,仅仅是处理异常
try{
}
catch(){
}

2. 一个try多个catch,一般对应的是被调用的函数,抛出多个异常的情况,分别处理。
try{
}
catch(){
}
catch(){
}
catch(){
}
注意:在多catch语法上的特殊地方,如果catch中的异常类存在子父类。父类的catch一定要放在子类的下面,否则编译失败。

3. 不一定要处理异常,但是有资源需要释放
try{
}
finally{
}

函数必须声明异常

public void show() throws Exception{ //必须申明异常
        try{
            throw new Exception();
        }finally {
            
        }
    }

有catch,函数show就不需要声明异常

 public void show() {
        try{
            throw new Exception();
        }catch (Exception e){
            
        }
        finally {

        }
    }

11.12 覆盖中异常的使用

覆盖时:

  • 子类方法覆盖父类方法只能抛出父类方法异常或者该异常的子类。 如果父类父方法抛出多个异常,子类只能抛出父类异常的子集。
  • 原则:就是子类的异常必须要在父类的异常处理控制中。
package day11;

/*
Exception
        -----------AException
        ----------------------AAException
        -----------BException
*/

class AException extends Exception{
    AException(){
        super();
    }
    AException(String message){
        super(message);
    }
}

class AAException extends AException{
    AAException(){
        super();
    }
    AAException(String message){
        super(message);
    }
}

class BException extends Exception{
    BException(){
        super();
    }
    BException(String message){
        super(message);
    }
}

class Fu{
    void show() throws AException{
        System.out.println("fu show");
        throw new AException("A 异常");

    }
}

class Zi extends Fu{
    void show() throws AException{//或者抛出AAException, 但是不能抛出BException
        System.out.println("zi show");
        throw new AException("A 异常");
    }
}

class Tool{
    void method(Fu f){
        try {
            f.show();
        }catch (AException e){
            System.out.println(e.toString());

        }

    }
}
public class ExceptionDemo7 {
    public static void main(String[] args){
        Tool tool = new Tool();
        tool.method(new Zi());  
        /*
        输出
        zi show
        day14.AException: A 异常
        */
    }
}

注意:有一种情况,只能try不能throws
被覆盖的方法没有抛出异常。
那么子类在覆盖时,子类方法中发生了异常,就只能try,无法throws声明。

interface Inter{
    void show();
}

class Demo implements Inter{
    public void show(){  // 这里不能用throws声明异常
        try {
            throw new Exception();
        }
        catch (Exception e){
            throw new RuntimeException("");
            //将编译时检测异常,转换成运行时的异常,这样就可以不用声明异常
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值