Java基础学习 ---异常

109 阅读8分钟

异常

Java基础学习---点击进入学习

640 (17).jpg

1.异常体系结构介绍

Throwable

Error(错误,仅靠程序本身无法恢复的错误) Exception(异常,因为代码导致的各种不正常情况)

Exception分为

​ 运行时异常(RuntimeException):RuntimeException及其子类都属于运行时异常

​ 检查(受检)异常(CheckedException):除了运行时异常以外的其他异常属于检查异常

2.try-catch处理异常

try : try代码块中用于执行可能出现异常的代码

catch : catch结构用于捕获可能出现的异常

try 不能单独出现 必须结合catch 或者 catch-finally 或者 finally

catch 也不能单独出现

捕获的异常和出现异常 类型匹配则能顺利捕获到 如果类型不匹配 则程序依然中断



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

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 10:13
 *  try : try代码块中用于执行可能出现异常的代码
 *  catch : catch结构用于捕获可能出现的异常
 *
 *  try 不能单独出现 必须结合catch 或者 catch-finally 或者 finally
 *  catch 也不能单独出现
 *
 *  捕获的异常和出现异常 类型匹配则能顺利捕获到 如果类型不匹配 则程序依然中断
 *
 */
public class TestTryCatch1 {
    public static void main(String[] args) {
        try{
            Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
        }catch(InputMismatchException e){
            System.err.println("出现了异常");
            e.printStackTrace(); // 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
        }

        System.out.println("感谢使用本程序!");
    }
}

使用try-catch结构捕获多个异常

如果在try结构中可能出现多种异常 我们可以使用多个catch块来捕获不同的异常

多个catch书写注意顺序,先子类 后父类 否则编译报错

不推荐直接使用异常父类 Exception捕获所有异常的这种写法 因为代码阅读性差



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

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 10:27
 *  使用try-catch结构捕获多个异常
 *
 *  如果在try结构中可能出现多种异常 我们可以使用多个catch块来捕获不同的异常
 *  多个catch书写注意顺序,先子类 后父类 否则编译报错
 *  不推荐直接使用异常父类 Exception捕获所有异常的这种写法 因为代码阅读性差
 */
public class TestTryCatch2 {
    public static void main(String[] args) {
        try{
            Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
        }catch(InputMismatchException  e){ // JDK1.5 支持使用或 分割两个异常类型  | ArithmeticException
            System.err.println("出现了输入不匹配异常");
            e.printStackTrace(); // 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
        }catch(ArithmeticException e){
            System.err.println("出现了算数运算异常");
            e.printStackTrace();// 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
        }catch(Exception  e){
            System.err.println("出现了其他异常");
            e.printStackTrace();
        }

        System.out.println("感谢使用本程序!");
    }
}

3.finally处理异常

finally关键字:finally代码块 表示用于处理任何情况下都需要执行的代码

不管是否出现异常 以及 异常是否被捕获到

finally不能单独出现 必须结合 try-catch 或者 try结构

finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机



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

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 10:38
 *  finally关键字:finally代码块 表示用于处理任何情况下都需要执行的代码
 *  不管是否出现异常 以及 异常是否被捕获到
 *
 *  finally不能单独出现 必须结合 try-catch  或者 try结构
 *
 *  finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
 *
 */
public class TestFinally1 {
    public static void main(String[] args) {
        try{
            Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
        }catch(InputMismatchException e){
            e.printStackTrace();
        }finally{
            System.out.println("感谢使用本程序!");
        }


    }
}

finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机

System.exit(int status) :System类中提供的静态方法 作用为退出JVM虚拟机

参数为int类型 传入任何数值作用相同

含义不同 : 0表示正常退出 非0表示非正常退出



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

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 10:41
 *  finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
 *
 *  System.exit(int status) :System类中提供的静态方法 作用为退出JVM虚拟机
 *  参数为int类型 传入任何数值作用相同
 *  含义不同 : 0表示正常退出 非0表示非正常退出
 */
public class TestFinally2 {
    public static void main(String[] args) {
        try{
            Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
            System.exit(0);
        }catch(InputMismatchException e){
            e.printStackTrace();
        }finally{
            System.out.println("感谢使用本程序!");
        }
    }
}

finally面试题:

1.try中存在return finally中的代码是否还执行

​ 执行

2.try中书写了return语句 返回了结果 finally中对返回值的操作是否还会影响返回值

​ 如果是基本数据类型 不影响

​ 如果是引用数据类型 影响



import java.util.Arrays;

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 10:47
 *  finally面试题:
 *      1.try中存在return finally中的代码是否还执行
 *          执行
 *      2.try中书写了return语句 返回了结果 finally中对返回值的操作是否还会影响返回值
 *          如果是基本数据类型 不影响
 *          如果是引用数据类型 影响
 */
public class TestFinally3 {
    public static int m1(){
        int num = 10;
        try {
            num++;
            return num;
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            num++;
        }
        return num;
    }

    public static int[] m2(){
        int [] nums = {1,2,3,4,5};
        try{
            return nums;
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            for (int i = 0; i < nums.length; i++) {
                nums[i]++;
            }
        }
        return nums;
    }


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

        System.out.println(Arrays.toString(m2()));
    }
}

4. throw和throws

throw : 用于抛出异常 书写在方法体内 作为一条单独的语句书写 一句只能抛出一个异常

需要根据抛出的异常不同,决定是否要声明

​ 如果抛出的为运行时异常,则不必声明

​ 如果抛出的为检查异常,则必须声明

throws : 用于声明异常 书写在方法声明形参列表之后 可以声明多个异常 多个异常之间使用逗号分割

调用者需要根据声明的异常类型不同,做出不同的处理

运行时异常,调用者无需处理

​ 检查异常,调用者必须处理

​ 1.使用try-catch处理

​ 2.继续声明给JVM虚拟机(不处理)



import java.io.IOException;
import java.sql.SQLException;

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 14:11
 *  throw : 用于抛出异常 书写在方法体内 作为一条单独的语句书写  一句只能抛出一个异常
 *      需要根据抛出的异常不同,决定是否要声明
 *      如果抛出的为运行时异常,则不必声明
 *      如果抛出的为检查异常,则必须声明
 *
 *  throws : 用于声明异常 书写在方法声明形参列表之后 可以声明多个异常 多个异常之间使用逗号分割
 *
 *  调用者需要根据声明的异常类型不同,做出不同的处理
 *      运行时异常,调用者无需处理
 *      检查异常,调用者必须处理
 *          1.使用try-catch处理
 *          2.继续声明给JVM虚拟机(不处理)
 *
 */
public class TestThrowThrows {
    public static void m1() throws ArithmeticException{
        System.out.println(10 / 0);
    }

    public static void m2() throws ClassNotFoundException{}

    public static void m3() throws SQLException {}

    public static void m4() throws RuntimeException{}

    public static void m5(){
        throw new RuntimeException("运行时异常");
    }

    public static void m6() throws IOException {
        throw new IOException();
    }

    public static void main(String[] args) throws SQLException {
        try {
            m6();
        } catch (IOException e) {
            e.printStackTrace();
        }

        m5();

        m1();

        try {
            m2();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        m3();
        m4();
    }

}



/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 14:23
 *  人类
 *      属性:名字 年龄
 */
public class Person {
    private String name;
    private int age;

    private char sex;

    public char getSex() {
        return sex;
    }



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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age > 0 && age <= 130){
            this.age = age;
        }else{
            throw new RuntimeException("年龄不合法:"+ age +",有效范围为:1 ~ 130" );
        }
    }
    public void setSex(char sex) throws Exception {
        if(sex == '男' || sex == '女'){
            this.sex = sex;
        }else{
            throw new Exception("性别不合法:" + sex);
        }

    }

    public String getName() {
        return name;
    }

    public static void main(String[] args) {
        Person p1 = new Person();

        p1.setName("赵四");

        p1.setAge(100);

        try {
            p1.setSex('中');
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("程序结束");
    }
}

5.自定义异常

自定义异常:当JDK提供的异常不能满足开发需求,我们需要自定义异常

1.继承异常父类 Throwable Exception RuntimeException 三者任意其中一个

2.编写有参构造方法初始化异常信息

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 14:23
 *  人类
 *      属性:名字 年龄
 */
public class Person {
    private String name;
    private int age;

    private char sex;

    public char getSex() {
        return sex;
    }



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

    public int getAge() {
        return age;
    }

    public void setAge(int age) throws InputAgeOutOfBoundsException {
        if(age > 0 && age <= 130){
            this.age = age;
        }else{
            throw new InputAgeOutOfBoundsException("年龄不合法:"+ age +",有效范围为:1 ~ 130" );
        }
    }
    public void setSex(char sex) {
        if(sex == '男' || sex == '女'){
            this.sex = sex;
        }else{
            throw new InputSexException("性别不合法:" + sex);
        }

    }

    public String getName() {
        return name;
    }

    public static void main(String[] args) throws InputAgeOutOfBoundsException {
        Person p1 = new Person();

        p1.setName("赵四");

        p1.setAge(110);

        p1.setSex('6');

        System.out.println("程序结束");
    }
}

/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 14:38
 *  自定义异常:当JDK提供的异常不能满足开发需求,我们需要自定义异常
 *      1.继承异常父类 Throwable Exception RuntimeException 三者任意其中一个
 *      2.编写有参构造方法初始化异常信息
 *
 */
public class InputAgeOutOfBoundsException extends Throwable{
    public InputAgeOutOfBoundsException(String message){
        super(message);
    }
}


/**
 * @author WHD
 * @description TODO
 * @date 2024/1/15 14:44
 */
public class InputSexException extends RuntimeException{
    public InputSexException(String message){
        super(message);
    }
}