异常的捕获和处理

目录

一、异常

1.异常概述

1.1认识异常

1.2Java异常体系结构

2.Java异常处理机制

2.1异常处理

2.2捕获异常

2.2.1使用try-catch捕获异常

2.2.2使用try-catch-finally处理异常

2.2.3使用多重catch处理异常

2.3抛出异常

2.3.1使用throws声明抛出异常

2.3.2使用throw抛出异常

2.4自定义异常

2.5异常链


一、异常

1.异常概述
1.1认识异常

异常是指程序在运行过程中出现的非正常情况。

public class Main {

    public static void main(String[] args) {
        int i=1,j=0,res;
        System.out.println("begin");
        res=i/j;//算术运算异常
        System.out.println("end");
    }

}

一旦程序发生异常将会立即结束,因此“end”没有输出。

1.2Java异常体系结构

异常在Java中被封装成了各种异常类。

程序中常见的异常: 

Exception设计时异常异常层次结构的根类
IOException设计时异常IO异常的根类,属于非运行时异常
FileNotFoundException设计时异常文件操作时,找不到文件
RuntimeException运行时异常运行时异常的根类,RuntimeException及其子类,不要求必须处理
ArithmeticException运行时异常算术运算异常
lllegalArgumentException运行时异常方法接收到非法参数
ArrayIndexOutOfBoundsException运行时异常数组越界访问异常
NullPointerException运行时异常尝试访问null对象的成员时发生的空指针异常
ArrayStoreException运行时异常数据存储异常,写数组操作时,对象或数据类型不兼容
ClassCastException运行时异常类型转换异常
IIIegalThreadStateException运行时异常试图非法改变线程状态,例如试图启动一个已经运行的线程
NumberFormatException运行时异常数据格式异常,试图把一字符串非法转换成数值
2.Java异常处理机制
2.1异常处理

Java中的异常处理机制依靠5个关键字:try、catch、finally、throw、throws。这些关键字提供了两种异常处理方式:

(1)用try、catch、finally来捕获和处理异常

try块中包含可能会抛出异常的代码

catch块中用户捕获和处理指定类型的异常

finally块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作

(2)使用throw、throws来抛出异常

throw关键字用于手动抛出异常对象。

throws关键字用于在方法声明中指定可能抛出的异常类型,表示该方法可能会抛出该类型的异常,由调用者来处理。

2.2捕获异常
2.2.1使用try-catch捕获异常
public class Main {

    public static void main(String[] args) {
        try {
            int i=1,j=0,res;
            System.out.println("begin");
            res=i/j;
            System.out.println("end");
        }catch (Exception e){
            System.out.println("caught");
            e.printStackTrace();
        }
        System.out.println("over");
    }

}
  • 如果try语句块中的所有语句正常执行完毕,没有发生异常,那么catch语句块中的所有语句将被忽略。
  • 如果try语句块在执行过程中发生异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try语句块中剩下的代码都将被忽略,相应的catch语句块将会被执行。匹配是指catch中所处理的异常类型与try中发生的异常类型完全一致或者是它的父类。
  • 如果try语句块在执行过程中发生异常,而抛出的异常在catch语句块中没有被声明,那么程序立即终止运行,程序被强迫退出。
  • catch语句块中可以加入用戶自定义处理信息,也可以调用异常对象的方法输出异常信息,常用的方法如下:
    void prinStackTrace() :输出异常的堆栈信息。堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用的栈序列。
    String getMessage() :返回异常信息描述字符串,该字符串描述了异常产生的原因,是 printStackTrace() 输出信息的一部分。
2.2.2使用try-catch-finally处理异常

无论try块中是否发生异常,finally语句块中的代码总能被执行。

public class Main {

    public static void main(String[] args) {
        try {
            int i=1,j=0,res;
            System.out.println("begin");
            res=i/j;
            System.out.println("end");
        }catch (ArithmeticException e){
            System.out.println("caught");
            e.printStackTrace();
        }finally {
            System.out.println("finally");
        }
        System.out.println("over");
    }

}
  • 如果try语句块中所有语句正常执行完毕,程序不会进入catch语句块执行,但是finally语句块会被执行。 
  • 如果try语句块在执行过程中发生异常,程序会进入到catch语句块捕获异常, finally语句块也会被执行。
  • try-catch-finally结构中try语句块是必须存在的,catch、finally语句块为可选,但两者至少出现其中之一。

即使在catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。

finally语句块中语句不执行的唯一情况是在异常处理代码中执行了 System.exit(1) ,退出Java虚拟机。

public class Main {

    public static void main(String[] args) {
        try {
            int i=1,j=0,res;
            System.out.println("begin");
            res=i/j;
            System.out.println("end");
        }catch (ArithmeticException e){
            System.out.println("caught");
            e.printStackTrace();
            System.exit(1);
        }finally {
            System.out.println("finally");
        }
        System.out.println("over");
    }

}

public class Main {

    public static void main(String[] args) {
        System.out.println(method());
    }

    private static int method() {
        int i=1;
        try {
            i++;//2
            System.out.println("try block,i="+i);//try block,i=2
            return i;//2
        }catch (Exception e){
            i++;
            System.out.println("catch block,i="+i);
        }finally {
            i=10;
            System.out.println("finally block,i="+i);//finally block,i=10
        }
        return i;
    }
}

 

public class Main {

    public static void main(String[] args) {
        System.out.println(method());
    }

    private static int method() {
        int i=1;
        try {
            i++;
            System.out.println("try block,i="+i);//try block,i=2
            return i;
        }catch (Exception e){
            i++;
            System.out.println("catch block,i="+i);
            return i;
        }finally {
            i=10;
            System.out.println("finally block,i="+i);//finally block,i=10
            return i;//10
        }
    }
}

2.2.3使用多重catch处理异常

catch语句块的排列顺序必须是从子类到父类,最后一个一般是Exception类。这是因为在异常处理中,catch语句块会按照从上到下的顺序进行匹配,系统会检测每个catch语句块处理的异常类型,并执行第一个与异常类型匹配的catch语句块。如果将父类异常放在前面,子类异常的catch语句块将永远不会被执行,因为父类异常的catch语句块已经处理了异常。

一旦系统执行了与异常类型匹配的catch语句块,并执行其中的一条catch语句后,其后的catch语句块将被忽略,程序将继续执行紧随catch语句块的代码。 

子类异常应该放在前面,父类异常应该放在后面。 

import java.util.InputMismatchException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            System.out.println("计算开始:");
            int i,j,res;
            System.out.println("请输入被除数:");
            i=input.nextInt();
            System.out.println("请输入除数:");
            j=input.nextInt();
            res=i/j;
            System.out.println(i+"/"+j+"="+res);
            System.out.println("计算结束");
        }catch (InputMismatchException e){
            System.out.println("除数和被除数都必须是整数!");
        }catch (ArithmeticException e){
            System.out.println("除数不能为0!");
        }catch (Exception e){
            System.out.println("其他异常"+e.getMessage());
        }finally {
            System.out.println("感谢使用本程序!");
        }
        System.out.println("程序结束!");
    }


}

第一种:被除数发生异常

 

 第二种:除数发生异常

第三种:除数为0

2.3抛出异常
2.3.1使用throws声明抛出异常

如果在一个方法体内抛出了异常,并希望调用者能够及时地捕获异常,Java语言中通过关键字throws声明某个方法可能抛出的各种异常,以通知调用者。throws可以同时声明多个异常,之间用逗号隔开。

import java.util.InputMismatchException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        try {
            divide();
        }catch (InputMismatchException e){
            System.out.println("除数和被除数都必须是整数!");
        }catch (ArithmeticException e){
            System.out.println("除数不能为0!");
        }catch (Exception e){
            System.out.println("其他异常"+e.getMessage());
        }finally {
            System.out.println("感谢使用本程序!");
        }
        System.out.println("程序结束!");
    }
    private static void divide() throws Exception{
        Scanner input=new Scanner(System.in);
        System.out.println("计算开始:");
        int i,j,res;
        System.out.println("请输入被除数:");
        i=input.nextInt();
        System.out.println("请输入除数:");
        j=input.nextInt();
        res=i/j;
        System.out.println(i+"/"+j+"="+res);
        System.out.println("计算结束");
    }

}
2.3.2使用throw抛出异常

在Java语言中,可以使用throw关键字来自行抛出异常。

package structure;

public class Main {
    public static void main(String[] args) {
        Person1 person=new Person1();
        try {
            person.setName("扈三娘");
            person.setAge(18);
            person.setGender("男女");
            person.print();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
class Person1{
    private String name="";
    private int age=0;
    private String gender="男";

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) throws Exception{
        if ("男".equals(gender)||"女".equals(gender)){
            this.gender = gender;
        }else {
            throw new Exception("性别必须是男或女!");
        }

    }
    public void print(){
        System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);
    }
}

  • 如果 throw 语句抛出的异常是 Checked 异常,则该 throw 语句要么处于 try 块里,显式捕获该异常,要么放在一个带 throws 声明抛出的方法中,即把该异常交给该方法的调用者处理; 
  • 如果 throw 语句抛出的异常是 Runtime 异常,则该语句无须放在 try 块里,也无须放在带 throws 声明抛出的方法中;程序既可以显式使用 try...catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给该方法调用者处理。
  • 自行抛出Runtime 异常比自行抛出Checked 异常的灵活性更好。同样,抛出 Checked 异常则可以让编译器提醒程序员必须处理该异常。

 throw和throws的区别:

1.作用不同:throw用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常。
2.使用位置不同:throw位于方法体内部,可以作为单独的语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
3.内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个。

2.4自定义异常

当JDK中的异常类型不能满足程序的需要时,可以自定义异常类。步骤:

①定义异常类,并继承Exception或者RuntimeException。

②编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法。

③实例化自定义异常对象,并在程序中使用throw抛出。

package structure;

public class Main {
    public static void main(String[] args) {
        Person1 person=new Person1();
        try {
            person.setName("扈三娘");
            person.setAge(18);
            person.setGender("男女");
            person.print();
        }catch (GenderException e){
            e.printStackTrace();
        }
    }
}
//自定义异常类
class GenderException extends Exception{
    public GenderException(String message){
        super(message);
    }
}
class Person1{
    private String name="";
    private int age=0;
    private String gender="男";

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) throws GenderException{
        if ("男".equals(gender)||"女".equals(gender)){
            this.gender = gender;
        }else {
            throw new GenderException("性别必须是男或女!");
        }

    }
    public void print(){
        System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);
    }
}

自定义异常可能是编译时异常,也可能是运行时异常 。

1.如果自定义异常类继承Excpetion,则是编译时异常。
特点:方法中抛出的是编译时异常,必须在方法上使用throws声明,强制调用者处理。
2.如果自定义异常类继承RuntimeException,则运行时异常。
特点:方法中抛出的是运行时异常,不需要在方法上用throws声明。

2.5异常链

有时候我们会捕获一个异常后再抛出另一个异常。

顾名思义就是将异常发生的原因一个传一个串起来,即把底层的异常信息传给上层,这样逐层抛出。

在要抛出的对象中使用 initCause() 方法,添加上一个产生异常的信息; getCause() 可以获取当前异常对象的上一个异常对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
异常捕获处理是在程序运行过程中遇到错误时,通过捕获异常并采取相应的处理措施,使程序能够继续执行而不中断。 在Python中,可以使用try-except语句来捕获异常。try块中放置可能会出现异常的代码,而except块中定义对异常处理逻辑。 下面是一个简单的示例: ```python try: # 可能会出现异常的代码 x = 10 / 0 except ZeroDivisionError: # 处理 ZeroDivisionError 异常 print("除数不能为零") ``` 在上面的代码中,try块中的代码尝试进行除法运算,如果除数为零,就会抛出ZeroDivisionError异常。而except块中的代码会捕获这个异常,并输出相应的提示信息。 除了捕获特定的异常类型,还可以使用except块来捕获所有类型的异常,例如: ```python try: # 可能会出现异常的代码 x = 10 / 0 except: # 处理所有类型的异常 print("发生了异常") ``` 在这种情况下,无论抛出什么类型的异常,都会被except块捕获处理。 除了使用except块来处理异常,还可以使用finally块来定义无论是否发生异常都需要执行的代码。例如: ```python try: # 可能会出现异常的代码 x = 10 / 0 except ZeroDivisionError: # 处理 ZeroDivisionError 异常 print("除数不能为零") finally: # 无论是否发生异常都会执行的代码 print("程序执行完毕") ``` 在上面的代码中,无论是否发生异常,finally块中的代码都会执行。 通过合理地使用try-except语句,可以帮助我们处理程序运行时可能出现的异常,增加程序的健壮性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

樱桃桃桃桃桃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值