一文读懂java异常(我们为什么要抛出去一个异常对象)

异常:Exception
1、分类:
1、编译期异常:checkedException。
在代码中存在该异常,是不能编译通过的,即不能生成.class文件,必须处理完所有的编译期异常才能运行代码。
2、运行期异常:RuntimeException
运行过程中抛出的错误。
2、JDK常见异常:
1、运行期异常:
NUllPointerWxception 空指针异常,使用了没有实例化的对象引用。
ArithmeticException 算数异常,被0除了
InputMissmatchException 输入类型不匹配异常,输入了非法字符
ArrayIdexOutOfBoundsException 数组下标越界异常,访问了不存在的数组的下标。
2、编译期异常:
IOException 输入输出异常,属于编译期异常,访问了一个不存在的文件或者目录。
3、JDK常见异常的继承关系
一文读懂java异常(我们为什么要抛出去一个异常对象)_第1张图片
基本上就是checkedException→Exception→Throwable→Object
或者RuntimeException→Exception→Throwable→Object
下面我会通过一个例子来看SUN公司如何定义异常来理解异常之间的继承关系。
4、那么我们遇到异常该怎么办呢?
思路有2:
1、自己能解决就解决。专业术语叫try-catch-finally
2、不能解决的话,谁用的话让谁去解决。即抛出异常让调用者去解决。那么所有的调用者都不解决的话,最终会交给JVM来解决,JVM会抛出简单异常信息。专业术语叫throws
我们首先来讲try-catch-finally
语法:

try{
//try代码块写圈住可能会出现异常的代码
	}catch(catch参数 形参){//catch参数:写可能会出现异常的对象类型
//catch代码块,当异常产生的时候会执行
}

使用try-catch的程序执行的流程:
一、没有异常的情况:
1、执行try代码块中的所有的代码
2、跳过catch代码块中的所有代码
3、执行catch代码块后边的代码
二、try代码块中出现异常
1、try代码块中出现异常(产生了一个异常对象),try块中后续代码会被跳过。
2、如果产生的异常对象是catch参数中的异常类型的实例,那么该异常对象会被捕获。catch形参变量(通常是e)指向被捕获的对象。通过变量e就可以操作被捕获的异常对象。执行catch代码块中的代码。
3、如果产生的异常对象不是catch参数中的一场类型的实例,程序崩溃。
4、如果捕获了产生的异常对象,执行完catch代码块后,执行catch后的内容。程序正常结束。
下面通过一个计算器例子来理解其用法

public class TestException {
    public static void main(String[] args) {

            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入除数:");
            int num0 = scanner.nextInt();
            System.out.println("请输入被除数:");
            int num1 = scanner.nextInt();
            int result = 0;
        try {
            result = num0 / num1;
            System.out.println("计算结果为:" + num0 + "/" + num1 + "=" + result);
            //上面的代码一旦产生了异常,那么会跳过try代码块中后续的代码,执行catch 中的代码
        } catch (ArithmeticException e) {
            //打印
            e.printStackTrace();
            System.out.println("您输入了非法的除数,不能为0,请您下次注意,不是我们的责任哦!");
        }
    }

}

5、那么有多个代码块可能出现异常呢?
此时我们需要多重try-catch

public class TestException {
    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入除数:");
            int num0 = scanner.nextInt();
            System.out.println("请输入被除数:");
            int num1 = scanner.nextInt();
            int result = 0;
            result = num0 / num1;
            System.out.println("计算结果为:" + num0 + "/" + num1 + "=" + result);
        } catch (ArithmeticException e) {
            //打印
            e.printStackTrace();
            System.out.println("您输入了非法的除数,不能为0,请您下次注意,不是我们的责任哦!");
        }
        catch (InputMismatchException e){
            e.printStackTrace();
            System.out.println("您输入了非数值型的数据,不能进行除法运算!请重新输入!");
        } catch (Exception e){
            e.printStackTrace();
            System.out.println("非法的操作!");
        }
    }
}

这时我们需要注意的是

catch (Exception e){
            e.printStackTrace();
            System.out.println("非法的操作!");
        }

只能放到最后,因为他的异常类型范围是最大的。如果放在其他异常类型前边,会报如下错误:其他类型异常已经捕获。它可以捕获所有的异常对象。Exception 是所有的异常类型的父类。一文读懂java异常(我们为什么要抛出去一个异常对象)_第2张图片
6、finally的使用
finally代码块中放在catch的后面,一般是存放不论何种情况一定都要执行的代码。如果某些代码是必须要被执行的,放到其中。
其中:用到了异常对象常用的两个方法:
System.exit(0):结束虚拟机
e.printStackTrace:打印被捕获异常对象的堆栈信息,通过该信息可以定位异常位置。

public class TestException {
    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入除数:");
            int num0 = scanner.nextInt();
            System.out.println("请输入被除数:");
            int num1 = scanner.nextInt();
            //可能产生异常的代码
            int result = 0;
            result = num0 / num1;
            System.out.println("计算结果为:" + num0 + "/" + num1 + "=" + result);
            //上面的代码一旦产生了异常,那么会跳过try代码块中后续的代码,执行catch 中的代码
            //结束虚拟机。不会执行finally 中的代码。
            System.exit(0);
            //即使代码中存在return 语句,都会执行 finally代码块
            return;
        } catch (ArithmeticException e) {
            //打印
            e.printStackTrace();
            System.out.println("您输入了非法的除数,不能为0,请您下次注意,不是我们的责任哦!");
        }
        catch (InputMismatchException e){
            e.printStackTrace();
            System.out.println("您输入了非数值型的数据,不能进行除法运算!请重新输入!");
        } catch (Exception e){
            e.printStackTrace();
            System.out.println("非法的操作!");
        }
    }
}

7、我们来看看SUN公司是如何定义的异常类。
以File类中createNewFile()方法为例

public class IoException {
    public static void main(String[] args) throws IOException {
        test();
        //第一种方式
        File file=new File("x:/1.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //抛给调用者来处理异常
    //第二种方式
    static void test() throws IOException {
         File file=new File("c:/1.txt");
         file.createNewFile();
    }
}

报错信息如下:
一文读懂java异常(我们为什么要抛出去一个异常对象)_第3张图片
那么报错信息为什么是全包名:具体信息呢?
下面我们看SUN公司源码分析:
该方法定义的异常方法如下:
一文读懂java异常(我们为什么要抛出去一个异常对象)_第4张图片
抛出的异常对象需要重写toString方法,当打印对象的时候会显示报错信息。
该方法的toString写在父类中继承关系如下:
IOException>Exception>Throwable一文读懂java异常(我们为什么要抛出去一个异常对象)_第5张图片
一文读懂java异常(我们为什么要抛出去一个异常对象)_第6张图片
既然我们已经搞懂SUN公司是如何定义异常的,那我们能不能自己写一个异常类呢?
答案是当然可以。
我们先补充下知识点:
throw:是java 的关键字,在方法体中使用,后面跟的是异常对象,只能跟一个异常对象。用于在方法体中抛出一个异常对象。

throws:是 java 的关键字,在方法的参数列表后使用,后面跟的是异常的类型。可以跟多个异常类型,使用逗号分隔。用于声明方法使用的时候可能会抛出的异常对象的类型。
现在开始回答文章题目:我们为什么要抛出去一个对象?
因为对象重写toString方法后,会携带具体的报错信息。
好了,我们现在开始写自定义异常类:
定义:一个学生类具有性别属性,当设置性别的时候,如果传入的 不是 【男、女】那么抛出一个自定义性别异常:GenderException。
*创建一个学生类:
我们在设置性别的时候做了如代码中的处理

public class Student {
    private String name;
    private String gender;

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

    public void setGender(String gender) throws Exception{
        if(!(gender.equals("男")||gender.equals("女"))){
            throw new GenderException(gender);
        }
        this.gender = gender;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

定义异常类
一文读懂java异常(我们为什么要抛出去一个异常对象)_第7张图片
测试类:

public class DefinedStudentException {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("小红");
        try {
            s.setGender("男o");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(s);
    }
}

在这里插入图片描述
简言之,try-catch,try-finally,try-catch-finally
完活!

你可能感兴趣的:(一文读懂系列,java)