java中的异常

目录

异常 

运行时异常和编译时异常的区别?

异常的作用

捕获异常

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

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

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

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

异常中的常见方法 

getMessage 

 tostring()                        

printstackTrace()              

抛出处理

throws

throw

练习 

键盘录入数据

自定义异常



异常 

1.异常是什么?

  • 程序中可能出现的问题

2.异常体系的最上层父类是谁?异常分为几类?

  • 父类:Exception。
  • 异常分为两类:编译时异常、运行时异常

3.编译时异常和运行时异常的区别?

  • 编译时异常:没有继承RuntimeExcpetion的异常,直接继承于Excpetion。编译阶段就会错误提示(如:日期解析异常)
  • 运行时异常:RuntimeException本身和子类,编译阶段没有错误提示,运行时出现的(如:数组索引越界异常)

 可以看到这个地方时报错,这就是编译时异常(在编译阶段,必须手动处理,否则代码报错)


 

数组越界异常,这就是运行时异常(在编译阶段是不需要处理的,是代码运行时出现的异常)

运行时异常和编译时异常的区别?

  • 编译时异常:除了RuntimeExcpetion和他的子类,其他都是编译时异常。编译阶段需要进行处理,作用在于提醒程序员。
  • 运行时异常:RuntimeException本身和所有子类,都是运行时异常,编译阶段不报错 

异常的作用

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

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

Student类 

package youjunjie;

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>40){
            System.out.println("年龄超出范围");
        }
        else{
        this.age = age;}
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

 

 

调用处调用了Student类里的代码,Student类并没有把复制的结果告诉调用者,而是直接打印在了控制台 ,调用者根本不知道赋值的结果,我们就可以用异常去解决

这个时候在控制台就会告诉异常的问题 

处理异常的方式有两种:

  1. 使用try-catch块捕获和处理异常。可以在try块中放置可能抛出异常的代码,然后在catch块中处理异常。
  2. 使用throws关键字将异常抛出给上层调用者处理。在方法声明中声明可能抛出的异常,然后由调用该方法的代码去处理异常。

处理异常的目的是保证程序的稳定性和可靠性,避免程序因为异常而崩溃或出现错误。


捕获异常

try {
可能出现异常的代码;
} catch(异常类名 变量名){

异常的处理代码;

}

目的:当代码出现异常时可以让程序继续往下执行。

 这里是数组越界直接就报错了,我们可以使用try catch👇


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

这个的运行结果会是什么呢?

这里把try里面所有的代码全部执行完毕,并没有执行catch里面的代码

我们再回到问题👇

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

会把try里面所有的代码全部执行完毕,不会执行catch里面的代码(只有当出现了异常才会执行catch里面的代码)

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

 

但实际上System.out.println(2/0);这一句代码并没有执行

但是对于多个问题我们就要写多个与之匹配的catch

如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面

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

会写多个catch与之对应

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

 这里会直接报错,相当于try catch的代码白写了,最后还是会交给虚拟机进行

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

相当于try catch的代码白写了,最后还是会交给虚拟机进行

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

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

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


异常中的常见方法 

public string getMessage()                
public string tostring()                        返回此可抛出的简短描述
public void printstackTrace()              把异常的错误信息输出在控制台

getMessage 

返回此 throwable 的详细消息字符串

 tostring()                        

返回此可抛出的简短描述

printstackTrace()              

在底层是利用system.err.println进行输出把异常的错误信息以红色字体输出在控制台

 printStackTrace的结果是通过红字显示出来的

仅仅是打印信息,不会停止程序运行

抛出处理

throws

注意:写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常 

throw

注意:写在方法内,结束方法。手动抛出异常对象,交给调用者。方法中下面的代码不再执行了 

通过代码我们来了解一下throw与throws

 

这个时候可以得出最大值,那如果数组为null呢

是不是就会报错了?

 这个时候我们可以使用throw跟throws抛出异常

也可以这样👇

也有可能数组会越界,与这个处理方法一样,下面来写一下优化后的代码

public class ExceptionDemo {
    public static void main(String[] args) {
        int[] arr={};
        int max = 0;
        try {
            max = getMax(arr);
        } catch (NullPointerException e) {
            System.out.println("空指针异常");
        }catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("索引越界异常");
        }
        System.out.println(max);
    }
    public static int getMax(int[] arr){
        if(arr==null){
            throw new NullPointerException();
        }
        if(arr.length==0){
            throw new ArrayIndexOutOfBoundsException();
        }
        int max=arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i]>max){
                max=arr[i];
            }
        }
        return max;
    }
}

练习 

键盘录入数据

需求:
键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在3~10之间,
年龄的范围为18-40岁
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况 

先写个GirlFriend类

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

    public GirlFriend() {
    }

    public GirlFriend(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 RuntimeException();
        }
        this.name = name;
    }

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

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

    public String toString() {
        return "GirlFriend{name = " + name + ", age = " + age + "}";
    }
}

 再写测试类

public class ExceptionTest {
    public static void main(String[] args) {
        /*键盘录入自己心仪的女朋友姓名和年龄。
        姓名的长度在3~10之间,
        年龄的范围为18-40岁
        超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
        提示:
        需要考虑用户在键盘录入时的所有情况。
        比如:录入年龄时超出范围,录入年龄时录入了abc等情况*/
        Scanner sc=new Scanner(System.in);
        GirlFriend gf = new GirlFriend();
        while (true) {
            try {
                System.out.println("请输入你心仪的女朋友的名字");
                String name = sc.nextLine();
                gf.setName(name);
                System.out.println("请输入你心仪的女朋友的年龄");
                String ageStr=sc.nextLine();
                int age = Integer.parseInt(ageStr);
                gf.setAge(age);
                //如果所有的数据都是正确的,那么跳出循环
                break;
            } catch (NumberFormatException e) {
                System.out.println("年龄的格式有误,请输入数字");
            }catch (RuntimeException e) {
                System.out.println("姓名的长度或年龄的范围有误");
            }
        }
        System.out.println(gf);

    }
}

自定义异常

  1. 定义异常类
  2. 写继承关系
  3. 空参构造
  4. 带参构造 

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

将之前的练习中的优化一下,加上姓名格式异常类,年龄范围异常类 

然后GirlFriend类的setAge与setName也要做相应的优化

 运行结果还会有相应的提示


这一期就到这里啦!!!感谢各位观看!!!

继续努力努力再努力!!!

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力敲代码的小火龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值