【Java】异常

文章介绍了Java中的异常处理机制,包括异常的基本概念,如Exception类和运行时异常与编译异常的区别。异常在程序中的作用是提供错误信息和作为方法返回值。文章详细阐述了异常的处理方式,包括JVM默认处理和程序员通过try-catch语句进行捕获。此外,还提出了自定义异常的必要性,并给出了创建自定义异常类的步骤和示例。
摘要由CSDN通过智能技术生成

一、异常介绍

异常是程序中可能出现的问题,用Exception表示
在这里插入图片描述
Exception:异常,代表程序可能出现的问题,通常用Exception以及它的子类来封装程序出现的问题
运行时异常:RuntimeException及其子类,在编译阶段不会出现异常提醒,在运行时会报错,如:数组的下标越界
编译异常:在编译阶段就会提醒的异常

二、异常的作用

1.用来查询bug的关键参考信息
如:数组越界异常

public class Test1 {
    public static void main(String[] args) {
        int[] arr = new int[3];
        System.out.println(arr[3]);
    }
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at Exception_test.Test1.main(Test1.java:6)

2.可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
①创建一个Student的类,并创建一个方法

public class Student {
    private int age;
    public void setAge(int age) {
        if(age<40&&age>18){
            this.age = age;
        }else{
            System.out.println("年龄超出范围");
        }
    }
}

②在测试类中调用此方法

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setAge(50);
    }
}

③运行后控制台显示的结果

年龄超出范围

进程已结束,退出代码为 0

这个程序的关系图
在这里插入图片描述
因此如果在被调用的方法中抛出异常,调用者就会得到异常的提示,从而选择处理该异常的方法

public class Student {
    private int age;
    public void setAge(int age) {
        if(age<40&&age>18){
            this.age = age;
        }else{
            throw new RuntimeException();
        }
    }
}

此时的运行结果为

Exception in thread "main" java.lang.RuntimeException
	at Exception_test.test2.Student.setAge(Student.java:9)
	at Exception_test.test2.Test.main(Test.java:6)

三、异常的处理方式

1.jvm默认的处理方案
①把异常的名称,异常的原因和异常出现的位置打印在控制台上
②程序停止执行,下面的代码不会再执行

2.捕获异常
格式:try{ //可能出现错误的代码 }catch (异常类名 变量名){ //异常的处理代码 }

public class Test3 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4};
        try{
            System.out.println(arr[10]);
        }catch (ArrayIndexOutOfBoundsException a){
            System.out.println("数组越界");
        }
        System.out.println("测试是否执行该语句");
    }
}

如果出现异常,将会执行catch中的语句,执行完成后继续执行下面的语句
其中的ArrayIndexOutOfBoundsException是程序出现异常的类名

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at Exception_test.Test1.main(Test1.java:6)

常见的问题:
①如果try中没有出现异常,则会将try中的代码执行完毕后执行catch后面的代码,不会执行catch中的代码
②如果try中遇到了多种异常,则需要在try后面写多个catch语句,分别对应每种异常(如果异常类种存在父子关系,父类要写到下面)
在jdk7之后,一个catch中可以捕获多个异常,中间用 | 隔开,如catch( 1 | 2),表示对这两种异常采用同一种处理方式
③如果try中出现的异常没有被捕获,则会采用jvm默认处理异常的方式
④如果try中的某一条语句出现了异常,则会跳转到catch中,不会执行该语句下面的语句

3.抛出异常
编译异常:必须要写
运行异常:可以不写
①throws:写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常,便于调用者对异常进行处理
格式:public void 方法名()throws 异常类名1,异常类名2…{}

public class Test4 {
    public static void main(String[] args) {
        int[] arr = null;
        try {
            getMax(arr);
        } catch (NullPointerException e) {
            System.out.println("测试");
        }
    }
    public static void getMax(int[] arr) throws NullPointerException{
        int max=0;
        for (int i = 0; i < arr.length; i++) {
            if(max<arr[i])max=arr[i];
        }
    }
}

②throw:写在方法内,结束方法,手动抛出异常对象,交给调用者
格式:public void 方法名(){throw new 异常类名();}

public class Test4 {
    public static void main(String[] args) {
        int[] arr = null;
        try {
            getMax(arr);
        } catch (NullPointerException e) {
            System.out.println("测试");
        }
    }
    public static void getMax(int[] arr){
        int max=0;
        for (int i = 0; i < arr.length; i++) {
            if(arr==null)throw new NullPointerException();
            if(max<arr[i])max=arr[i];
        }
    }
}

四、异常中常见的方法

1.public String getMessage();返回异常的原因

public class Test1 {
    public static void main(String[] args) {
        int[] arr = new int[3];
        try {
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException e) {
            String message = e.getMessage();
            System.out.println(message);
        }
    }
}
Index 3 out of bounds for length 3

2.public String toString();返回异常的名字和原因

public class Test1 {
    public static void main(String[] args) {
        int[] arr = new int[3];
        try {
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException e) {
            String message = e.toString();
            System.out.println(message);
        }
    }
}
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

3.public void printStackTrace();打印异常的名字,原因和地址

public class Test1 {
    public static void main(String[] args) {
        int[] arr = new int[3];
        try {
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }
}
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at Exception_test.Test1.main(Test1.java:7)

五、例题

创建一个学生类,构造方法为无参构造,定义年龄和姓名,设置姓名时长度范围为3-10,年龄的范围是18-40,并且给出输入数字之外的内容的处理方法,如在输入年龄时输入aaa(注:运行异常可以不用手动抛出异常)

1.创建学生对象,并抛出异常
在RuntimeException后的括号内可以自定义异常的原因

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

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length()<3||name.length()>10)throw new RuntimeException();
        else this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age<18||age>40)throw new RuntimeException();
        else this.age = age;
    }

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

2.创建测试类,并捕获异常

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Student s = new Student();
        boolean flag=true;
        do {
            try {
                System.out.println("请输入姓名:");
                String name = sc.next();
                s.setName(name);
                sc.nextLine();
                System.out.println("请输入年龄:");
                String s1 = sc.nextLine();
                int age=Integer.parseInt(s1);
                s.setAge(age);
                flag=false;
            } catch (NumberFormatException e){
                System.out.println("年龄输入的格式有误,请重新输入");
            } catch (RuntimeException e) {
                System.out.println("输入名字的长度或年龄的范围不符合要求,请重新输入");
            }
        }while(flag);
        System.out.println(s.toString());
    }
}

六、自定义异常

在上面的例题中,名字长度和年龄的范围都直接抛出RuntimeException,是运行异常的最顶级的父类,不能清晰描述出现的异常,并且在判断两者时不能将两者区分开,因此可以创建一个自定义异常(运行异常继承于RuntimeException,编译异常继承于Exception),用来具体描述这两种异常

定义异常类的步骤
①创建异常类
②写继承关系
③空参构造
④带参构造

1.用于年龄范围的异常

public class AgeOutOfBoundsException extends RuntimeException{
    public AgeOutOfBoundsException() {
    }

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

2.用于名字长度的异常

public class NameFormatException extends RuntimeException{
    public NameFormatException() {
    }

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

3.将抛出异常的两个方法修改为对应的自定义异常

public void setName(String name) {
        if(name.length()<3||name.length()>10)throw new NameFormatException("输入的姓名长度有误,请重新输入");
        else
        this.name = name;
    }
public void setAge(int age) {
        if(age<18||age>40)throw new AgeOutOfBoundsException("输入的年龄范围有误,请重新输入");
        else
        this.age = age;
    }

4.在catch中直接调用异常的方法,把异常的位置,名字和原因打印出来

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Student s = new Student();
        boolean flag=true;
        do {
            try {
                System.out.println("请输入姓名:");
                String name = sc.next();
                s.setName(name);
                sc.nextLine();
                System.out.println("请输入年龄:");
                String s1 = sc.nextLine();
                int age=Integer.parseInt(s1);
                s.setAge(age);
                flag=false;
            } catch (NumberFormatException e){
                e.printStackTrace();
            } catch (AgeOutOfBoundsException e) {
                e.printStackTrace();
            }catch (NameFormatException e){
                e.printStackTrace();
            }
        }while(flag);
        System.out.println(s.toString());
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值