Java_异常

介绍

编译时异常:

        除RuntimeException和他的子类,其他都是编译时异常。编译阶段需要进行处理,作用在于提醒程序眼

运行时异常:

        RuntimeException本身和其所有子类,都是运行时异常。编译阶段不报错,是程序运行时出现的。一般是由于参数传递错误带来的问题

作用:

        作用一:异常是用来查询bug的关键信息

        作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

异常演示:

数组越界
代码:
public class ExceptionDemo1 {
    public static void main(String[] args) {
        String[] arr = {"111","222","333"};
        System.out.println(arr[10]);
    }
}
运行结果:

抛出异常:

目的:

        告诉调用者出错了

格式:

        在方法体中:throw+异常对象

        在定义方法中:在方法后写 throws+可能出现的异常类型(只需要写编译时异常)

        题目要求:设定学生对象的年龄应位于18~22之间

代码:
学生类:
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        if(age < 18 || age > 22){
            throw new RuntimeException();
        }else {
            this.age = age;
        }
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
测试类:
public class ExceptionDemo2 {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setAge(30);
    }
}
运行结果:

JVM虚拟机默认处理异常的方式:

        1.把异常的名称,异常原因及异常出现的位置等信息以红色字体输出在控制台

        2.程序停止执行,异常下面的代码不会再执行

捕获异常:

目的:

        不让程序停止

格式:
格式一:

        try{

                可能出现异常的代码

        } catch(异常类名 变量名){

                出现上面小括号的异常类后的处理代码

        }

格式二:

        try{

                可能出现异常的代码

        } catch(异常类名 变量名){

                出现上面小括号的异常类后的处理代码

        } finally {

                被finally控制的语句一定会执行,除非JVM退出

        }

代码演示:
public class ExceptionDemo2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        try {
            //可能出现异常的代码
            System.out.println(arr[10]);
            //↑此处出现了异常,程序就会在这里创建一个ArrayIndexOutOfBoundsException对象
            //拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象
            //如果能接受,就表示该异常被捕获,执行catch里面对应的代码
            //当catch里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码
        } catch(ArrayIndexOutOfBoundsException e) {
            //如果出现了ArrayIndexOutOfBoundsException异常,则运行下面代码↓
            System.out.println("数组越界");
        }

        System.out.println("后续代码仍执行");

    }
}
运行结果:

问题思考:

问题1:

        如果try中没有遇到问题,怎么执行?

代码演示:
public class ExceptionDemo3 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        try {
            //可能出现异常的代码
            System.out.println(arr[0]);
        } catch(ArrayIndexOutOfBoundsException e) {
            //如果出现了ArrayIndexOutOfBoundsException异常,则运行下面代码↓
            System.out.println("数组越界");
        }

        System.out.println("后续代码仍执行");
    }
}
运行结果:

答案:

        会执行try中的所有代码,不会执行catch中的代码,会执行后续代码

问题2:

        如果try中可能遇到多个问题,怎么执行?

代码演示:
public class ExceptionDemo4 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        try {
            System.out.println(arr[10]);
            System.out.println(2/0);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界");
        }

        System.out.println("后续代码仍执行");
    }
}
运行结果:

答案:

        会执行到try中的出现异常的代码,不会执行后续代码,会执行出现指定异常类的catch中的代码,会执行后续代码,一般try中可能遇到多个问题的情况后面应写多个catch涵盖所有可能的异常类。并且如果要捕获多个异常,这些异常存在父子关系的话,那么父类要写到最下边。

问题3:

        如果try中遇到的问题没有被捕获,怎么执行?

代码演示:
public class ExceptionDemo5 {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        try {
            System.out.println(arr[10]);
        } catch (NullPointerException e) {
            System.out.println("空指针异常");
        }

        System.out.println("后续代码仍执行");
    }
}
运行结果:

答案:

        这种情况下没有捕获真正的异常,会采用JVM虚拟机默认处理异常的方式

问题4:

        如果try中遇到了问题,那么try下面的代码还会执行吗?

代码演示:
public class ExceptionDemo6 {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        try {
            System.out.println(arr[10]);
            System.out.println("----------");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界");
        }

        System.out.println("后续代码仍执行");
    }
}
运行结果:

答案:

        try下面的代码不会执行,直接跳转到对应的catch中,执行catch里面的语句体,如果没有对应的catch与之匹配,那么还是会交给虚拟机处理。

常见方法:

public String getMessage()      返回此throwable的详细消息字符串
public String toString()        返回此可抛出的简短描述
public void printStackTrace     把异常的错误信息以红色字体输出在控制台
                                在底层是利用System.err.println进行输出
                                细节:仅仅是打印信息,不会停止程序运行
代码演示:
public class ExceptionDemo7 {
    public static void main(String[] args) {
        /*
        public String getMessage()      返回此throwable的详细消息字符串
        public String toString()        返回此可抛出的简短描述
        public void printStackTrace     把异常的错误信息以红色字体输出在控制台
                                        在底层是利用System.err.println进行输出
                                        细节:仅仅是打印信息,不会停止程序运行
         */

        int[] arr = {1,2,3};
        try {
            System.out.println(arr[10]);
        } catch (ArrayIndexOutOfBoundsException e) {
            //public String getMessage()      返回此throwable的详细消息字符串
            String message = e.getMessage();
            System.out.println(message);
            System.out.println();
            //public String toString()        返回此可抛出的简短描述
            String str = e.toString();
            System.out.println(str);
            System.out.println();
            //public void printStackTrace     把异常的错误信息以红色字体输出在控制台
            e.printStackTrace();
        }

        System.out.println("后续代码仍执行");
    }
}
运行结果:

综合练习:

需求:
键盘录入人类对象的姓名和年龄
姓名的长度在3~10之间
年龄的范围为18~40岁
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止
提示:
需要考虑用户在键盘录入时的所有情况
比如:录入年龄时超出范围、录入年龄时录入abc等
代码:
public class ExceptionTest1 {
    public static void main(String[] args) {
        /*
        需求:
        键盘录入人类对象的姓名和年龄
        姓名的长度在3~10之间
        年龄的范围为18~40岁
        超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止
        提示:
        需要考虑用户在键盘录入时的所有情况
        比如:录入年龄时超出范围、录入年龄时录入abc等
         */

        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //创建人对象
        Person p = new Person();

        while (true) {
            try {
                //录入姓名
                System.out.println("请输入姓名");
                String name = sc.nextLine();
                p.setName(name);
                //录入年龄
                System.out.println("请输入年龄");
                String ageStr = sc.nextLine();
                int age = Integer.parseInt(ageStr);
                p.setAge(age);
                //没有异常直接跳出
                break;
            }catch (NumberFormatException e) {
                System.out.println("年龄格式不符合规范");
            } catch (RuntimeException e) {
                System.out.println("姓名或年龄不符合要求");
            }
        }
        System.out.println(p);
    }
}
运行结果:

自定义异常:

        意义:

                就是为了让控制台的报错信息更加的见名知意

        定义步骤:

                ①定义异常类

                ②写继承关系

                ③空参构造

                ④带参构造

        接下来使用自定义异常完善上述综合练习

代码演示:
异常类NameFormatException:
public class NameFormatException extends RuntimeException{
    public NameFormatException() {
    }

    public NameFormatException(String message) {
        super(message);
    }
}
异常类AgeOutOfBoundsException:
public class AgeOutOfBoundsException extends RuntimeException{
    public AgeOutOfBoundsException() {
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
    }
}
Person类:
public class Person {
    private String name;
    private int age;


    public Person() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        if(name.length() < 3 || name.length() > 10) {
            throw new NameFormatException(name + "不满足长度3~10要求");
        }
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        if (age < 18 || age > 40) {
            throw new AgeOutOfBoundsException(age + "不属于18~40范围");
        }
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }
}
测试类:
public class ExceptionTest1 {
    public static void main(String[] args) {
        /*
        需求:
        键盘录入人类对象的姓名和年龄
        姓名的长度在3~10之间
        年龄的范围为18~40岁
        超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止
        提示:
        需要考虑用户在键盘录入时的所有情况
        比如:录入年龄时超出范围、录入年龄时录入abc等
         */

        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        //创建人对象
        Person p = new Person();

        while (true) {
            try {
                //录入姓名
                System.out.println("请输入姓名");
                String name = sc.nextLine();
                p.setName(name);
                //录入年龄
                System.out.println("请输入年龄");
                String ageStr = sc.nextLine();
                int age = Integer.parseInt(ageStr);
                p.setAge(age);
                //没有异常直接跳出
                break;
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } catch (NameFormatException e) {
                e.printStackTrace();
            } catch (AgeOutOfBoundsException e) {
                e.printStackTrace();
            }
        }
        System.out.println(p);
    }
}
运行结果:

  • 30
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值