异常处理机制

发布时间 2023-09-21 17:39:08作者: nothing701

一、异常概述和分类(理解)

  • 概述
异常就是程序出现了例外
  • 为什么程序出错,控制台提示异常类
语言设计者,早已把所有的异常都设计成异常类,当程序出现异常,异常类的对象就被创建,控制台展示的是异常信息。
  • 异常的分类
         Throwable
        /         \
     Error      Exception
               /         \
   CheckedException   RuntimeException   
         ...                  \
                           ... 
   
   
  Throwable类是java语言中的所有错误和异常的基类。
  
  Error是Throwable子类,它表示错误。
  Exception是Throwable子类,它表示异常。
  
  Error和Exception区别?
   Error:错误,一般是环境、内存...程序员无法通过程序解决。
   Exception:异常,程序员需要处理。 
   
 
 
 CheckedException:不存在这个类,编译期异常。
 RuntimeException:存在这个类,运行时异常。
 如果遇到一个异常类,它只要是RuntimeException的子类,就一定是运行时异常,否则一定是编译期异常。
 
  • Throwable类的方法
public String getMessage()	返回此throwable的详细消息字符串。 
public String toString()	返回此 throwable 的简短描述
public void printStackTrace()	打印异常的堆栈的跟踪信息
package com.bjpowernode.javastudy.day18.exception01;

public class DemoException extends Throwable{

    public DemoException(String message) {
        super(message);
    }

}

package com.bjpowernode.javastudy.day18.exception01;

public class TestDemoException {
    public static void main(String[] args) {
      DemoException d1 = new DemoException("除数为0的就错误");
        System.out.println(d1.getMessage());
        System.out.println("----------------------");
        System.out.println(d1.toString());
        System.out.println("----------------------");
        d1.printStackTrace();
    }
}

二、Throw和Throws关键字(理解)

  • 为什么用throw ?
当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。

throw就是多一些提示信息。
package com.bjpowernode.javastudy.day18.exception02;

public class TestThrow01 {
    public static void main(String[] args) {
     int[] arr = {1,2,3};
        System.out.println(fun(arr,888));
       
    }

    //你给我数组,给我索引,我给你返回索引的数据
    public static int fun(int[] arr,int index) {
        if(index<0 || index>=arr.length){
            throw new ArrayIndexOutOfBoundsException("角标越界啦,赶紧改一下吧。。。");
        }
        return arr[index];
    }

}

  • 语法
抛出异常格式:throw new 异常类名(参数列表);
  • 为什么用Throws?
将问题标识出来,报告给调用者。
如果方法内通过throw 抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws关键字进行声明,让调用者去处理。

使用Throws可以暂时的把异常抛出,如果代码不出现参数传递错误,那么虚拟机也不会停止,但是一旦出现问题,虚拟机仍然停止!
package com.bjpowernode.javastudy.day18.exception02;

import java.io.UnsupportedEncodingException;

public class TestThrows01 {
    public static void main(String[] args) throws UnsupportedEncodingException{
      fun1();
    }

    public static void fun1() throws UnsupportedEncodingException{
          fun2();
    }
    public static void fun2() throws UnsupportedEncodingException{
        System.out.println("fun2....");
        //因为throw后面跟一个编译期异常,报错了,需要用throws来处理!
        throw new UnsupportedEncodingException("提示,字符串不支持。。");
    }
}

  • 语法
声明异常格式:[修饰符] 返回值类型 方法名(参数列表) throws 异常类名1, 异常类名2, … {	}

三、捕获异常(掌握)

  • try-catch
try{

}catch(异常类 对象名){ 
    对象名.printStackTrace();
}

解释:
try{ }可能发生的异常
catch(){} 捕获异常,当异常发生,就执行异常信息
package com.bjpowernode.javastudy.day18.exception03;

import java.io.UnsupportedEncodingException;

public class TestTryCatch01 {
    public static void main(String[] args)  {
        System.out.println("程序开始。。。");
        try {
            "abc".getBytes("asdfa");
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        System.out.println("程序结束。。。");
    }
}

package com.bjpowernode.javastudy.day18.exception03;

public class TestTryCatch01 {
    public static void main(String[] args)  {
        System.out.println("程序开始。。。");

        // try {
        //     "abc".getBytes("asdfa");
        //     Class.forName("sdaf");
        // } catch (UnsupportedEncodingException | ClassNotFoundException e) {
        //     e.printStackTrace();
        // }

        // try {
        //     "abc".getBytes("asdfa");
        //     Class.forName("sdaf");
        // } catch (UnsupportedEncodingException e) {
        //     e.printStackTrace();
        // } catch (ClassNotFoundException e) {
        //     e.printStackTrace();
        // }


        // try {
        //     "abc".getBytes("asdfa");
        //     try {
        //         Class.forName("sdaf");
        //     } catch (ClassNotFoundException e) {
        //         e.printStackTrace();
        //     }
        // } catch (UnsupportedEncodingException e) {
        //     e.printStackTrace();
        // }
     

        System.out.println("程序结束。。。");
    }
}

  • try-catch-finally
try{

}catch(异常类 对象名){ 
    对象名.printStackTrace();
}finally{
    finally语句是一定执行,一般用于IO流关闭资源。
}

package com.bjpowernode.javastudy.day18.exception03;

import java.io.UnsupportedEncodingException;

public class TestTryCatch02 {
    public static void main(String[] args)  {
        System.out.println("程序开始。。。");
        try {
            System.out.println("try...");
            "abc".getBytes("utf8");
            System.out.println("程序正在执行。。。");
            return;
            //System.exit(0);
        } catch (UnsupportedEncodingException e) {
            System.out.println("catch...");
            e.printStackTrace();
        }finally {
            System.out.println("我总是执行。。。");
        }
        System.out.println("程序结束。。。");
    }
}

package com.bjpowernode.javastudy.day18.exception03;

import java.io.UnsupportedEncodingException;

public class TestTryCatch02 {
    public static void main(String[] args)  {
        System.out.println("程序开始。。。");
        try {
            System.out.println("try1...");
            "abc".getBytes("utf8");
            System.out.println("程序正在执行getBytes。。。");

            try {
                System.out.println("try2...");
                Class.forName("com.bjpowernode.javastudy.day03.homework.Demo0111");
                System.out.println("程序正在执行forName。。。");
                return;
            } catch (ClassNotFoundException e) {
                System.out.println("catch...inner");
                e.printStackTrace();
            }finally {
                System.out.println("我总是执行。。。inner");

            }
            System.out.println("哈哈。。。");
            return;
        } catch (UnsupportedEncodingException e) {
            System.out.println("catch...outer");
            e.printStackTrace();
        }finally {
            System.out.println("我总是执行。。。outer");
        }

        System.out.println("程序结束。。。");
    }
}

  • try-finally(了解)
不会捕获异常,只要有异常,虚拟机关闭,后续程序不会执行。
package com.bjpowernode.javastudy.day18.exception03;

import java.io.UnsupportedEncodingException;

public class TestTryFinally {
    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
            "abc".getBytes("abc");
        } finally {
            System.out.println("我总是执行。。。");
        }
        
    }
}

四、自定义异常类(掌握)

只要继承Exception类或者Throwable,属于编译期异常
只要继承RuntimeException,属于运行时异常
package com.bjpowernode.javastudy.day18.exception04;

public class AgeOutOfBoundsException extends Exception{
    public AgeOutOfBoundsException() {
    }
    public AgeOutOfBoundsException(String message) {
        super(message);
    }
}

package com.bjpowernode.javastudy.day18.exception04;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) throws AgeOutOfBoundsException {
        this.name = name;
        setAge(age);
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) throws AgeOutOfBoundsException{
        if(age < 0 || age>150){
            //抛出异常???
            throw new AgeOutOfBoundsException("年龄超过界限的异常!");
        }
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package com.bjpowernode.javastudy.day18.exception04;

public class TestPerson {
    public static void main(String[] args)  {
        Person p1 = null;
        try {
            p1 = new Person("张三",200);
        } catch (AgeOutOfBoundsException e) {
            e.printStackTrace();
        }
        System.out.println(p1);
    }
}

五、异常其他问题(了解)

  • 方法重写异常问题
原则:子类声明的异常范围不能超过父类声明范围。
package com.bjpowernode.javastudy.day18.exception05;

public class Fu {

    public void fun()throws Exception{ }
}

package com.bjpowernode.javastudy.day18.exception05;
public class Zi extends Fu{
    @Override
    public void fun() throws Exception,RuntimeException {

    }
}
  • 异常链
捕获一个异常(范围大),再抛出一个异常(范围小)
package com.bjpowernode.javastudy.day18.exception06;

public class Test {
    public static void main(String[] args) {
        try {
            fun();
        } catch (DenominatorZeroException e) {
            e.printStackTrace();
        }
    }


public static void fun() throws DenominatorZeroException {

        try {
            System.out.println(1/0);
        } catch (ArithmeticException e) {
        
 throw new DenominatorZeroException("分母不能为零。");
        }

    }
}