当前位置:   article > 正文

Java基础-异常处理

Java基础-异常处理

文章目录

1.异常处理基础

1.异常处理快速入门

1.什么时候使用异常处理?

如果程序员认为一段程序可能出现错误的时候就可以使用异常处理,基本的try-catch是

try {
	可能出现异常的代码段
} catch (Exception e) {
	e.printStackTrace();//打印出异常的堆栈跟踪信息到标准错误流(通常是控制台)。它会显示异常发生的位置、异常的类型以及调用栈的层次
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用这种方法进行异常处理,即使程序出错也会继续运行之后的代码,一般适用于即使遇到了一些不那么严重的问题也不会使程序崩溃

异常处理快捷键 :ctrl + alt + t然后选择try-catch

2.异常介绍

1.基本概念

程序执行中发生的不正常情况称为异常,开发过程中的语法错误和逻辑错误不是异常

2.异常分类

  1. Error(错误):java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况,比如:

    1. StackOverflowError[栈溢出]
    2. OOM(out of memory)

    Error是严重错误,程序会崩溃

  2. Exception:其他因编程错误或偶然的外在因素导致的一致性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网路连接中断等,Exception分为两大类:

    1. 运行时异常
    2. 编译时异常

3.异常体系图

image-20231106155526173

异常体系图小结:

  1. 异常分为两大类,运行时异常和编译时异常
  2. 运行时异常,编译器不要求强制处置的异常。编译器检测不出来,一般是指编程时的逻辑错误
  3. 对于运行时异常可以不做处理,因为这类异常很普遍,若全做处理可能会对程序的可读性和运行效率产生影响
  4. 编译时异常,是编译器要求必须处理的异常(FileNotFoundException),不处理程序无法运行

4.五大运行时异常

1.NullPointerException 空指针异常

触发条件:

当应用程序试图使用该对象的时候,该对象为空

实例:
public class NullPointerException {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

image-20231106161221159

2.ArithmeticException 数学运算异常

触发条件:

当出现异常的运算条件时,抛出此异常。例如:一个整数“除以零”时,抛出此类的一个实例

3.ArrayIndexOutOfBoundsException 数组下标越界异常

触发条件:

用非法索引引发访问数组时抛出的异常。如果索引为负或者等于等于数组大小,则该索引为非法索引

实例:
public class ArrayIndexOutOfBoundsException {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        for (int i = 0; i <= arr.length; i ++){
            System.out.println(arr[i]);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

image-20231106162609846

4.ClassCastException 类型转换异常

触发条件:

当试图将对象强制转换为不是实例的子类时,抛出该异常

实例:
    public static void main(String[] args) {
        A b = new B(); //向上转型
        B b2 = (B)b; //向下转型
        C c2 = (C)b; //此时是不可以的,因为B和C类并没有关系,不能将B类的对象进行强转
    }
}

class A{}
class B extends A{}
class C extends A{}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

image-20231106164028982

5.NumberFormatException 数字格式不正确异常

触发条件:

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。使用异常可以确保输入是满足条件数字

实例:
public class NumberFormatException {
    public static void main(String[] args) {
        String name = "韩顺平教育";

        int num = Integer.parseInt(name); //这里的字符串并不能转换成int

        System.out.println(num);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

image-20231106165309257

5.编译异常(必须处理的异常)

  1. SQLException:操作数据库时,查询表可能发生异常
  2. IOException:操作文件时,发生的异常
  3. FileNotFoundException:当操作一个不存在的文件时发生的异常
  4. ClassNotFoundException:加载类,而该类不存在时,异常
  5. EOFException:操作文件,到文件末尾,发生异常
  6. IllegalArguementException:参数异常

2.try-catch异常处理机制

1.异常处理的方式

1.try-catch-finally

定义:

程序员在代码中捕获发生的异常,自行处理

示意图:

image-20231106215155425

2.throws

定义:

将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

示意图:

image-20231106215838138

解释:

假如f2方法将异常抛出,则应该由调用它的f1方法来处理,当然,f1方法也有两种选择,直接try-catch来处理或者继续将异常抛出到main方法…

2.try-catch-finally细节

1.如果异常发生了,则异常发生后面的代码都不会执行,直接进入到catch块

实例:
public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "史蒂夫";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("异常信息=" + e.getMessage());
        }
//        System.out.println("继续");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

image-20231106223131644

这里出现异常,则后面的输出数字+a的语句就没有被执行

2.如果异常没有发生,则顺序执行try的代码块,不会进入到catch

实例:
    public static void main(String[] args) {
        try {
            String str = "123";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("异常信息=" + e.getMessage());
        }
//        System.out.println("继续");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

image-20231106223413488

这里没有异常发生就没有执行catch中的语句

3.如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用finally

实例:
public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "史蒂夫";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("异常信息=" + e.getMessage());
        } finally {
            System.out.println("finally代码块被执行!");
        }
//        System.out.println("继续");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

image-20231106223001684

可以看到这里出现异常但是finally中的语句还是执行了

4.在异常处理最后的语句是否执行跟处理异常的方式有关

5.如果finally中有返回值,那么这个返回值一定会覆盖前面的返回值,如果finally没有返回值则,在这个方法结束之前,finally一定会被执行

6.可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointException在前),如果发生异常,只会匹配一个catch

实例:
public class TryCatchDetail02 {
    public static void main(String[] args) {
    //创建person对象然后调用getName方法
        try {
            Person person = new Person();
            person = null;
            String name = person.getName(); //NullPointerException
            System.out.println("name=" + name);
            int n1 = 10;
            int n2 = 0;
            int res = n1 / n2; //ArithmeticException
        }   catch (NullPointerException e) {
            System.out.println("空指针异常");
        }   catch (ArithmeticException e) {
            System.out.println("算术异常");
        }   catch (Exception e) {
            System.out.println(e.getMessage());
        }  finally {
            System.out.println("finally");
        }

    }
}

class Person {
    private String name = "jack";
    //获取这个name
    public String getName() {
        return name;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

7.可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此如果程序遇到异常会直接崩溃。应用场景:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑

实例:
public class TryCatchDetail03 {
    public static void main(String[] args) {
        try{
            int n1 = 10;
            int n2 = 0;
            System.out.println("res=" + (n1 / n2));
        }finally {
            System.out.println("finally");
        }
        System.out.println("继续执行");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3.try-catch异常处理练习

练习1

题目:

image-20231107163330764

解释:

会被空指针异常捕捉到,但是,因为在finally中有返回值所以会覆盖前面的3,返回4

练习2

题目:

image-20231107163728789

解释:

返回的是4

练习3

题目:

image-20231107164038201

解释:

finally中没有返回值,但是catch中有返回值,此时先执行catch的时候并不返回,而是将那个变量作为临时变量存储,然后继续将finally执行完,最后返回的是那个临时变量,所以最后的输出是 i = 4, 3

try-catch异常处理小结

  1. 如果没有出现异常,则执行try块中的所有语句,不执行catch块中语句,如果有finally,最后还要执行finally里面的语句
  2. 如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally中的语句

4.try-catch最佳实践

题目:

image-20231107181541297

代码:
public class TryCatchExercise04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); //创建Scanner对象
        while (true) { //循环读取
            System.out.println("请输入一个整数"); //提示输入
            String str = scanner.next(); //获取用户输入的字符串
            try {
                int num = Integer.parseInt(str); //将字符串转成int,如果出现异常,就会跳到catch
                System.out.println("num=" + num); //如果没有异常,就会执行这里
                break; //跳出循环
            } catch (NumberFormatException e) {
                System.out.println("输入的不是整数,请重新输入");
            }
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.throws异常处理

1.throws基本介绍

  1. 如果有一个方法中的语句可能生成某种异常,但是并不能确定如何处理,则此方法应显示地声明抛出异常,表明该方法将不对异常进行处理,而由该方法的调用者负责处理
  2. 在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是他的父类
  3. 被调用者抛出多少异常,调用者就要处理多少异常或者向上继续抛出

实例:

public class Throws01 {
    public static void main(String[] args) {
        try {
            test();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        //被调用的方法,抛出多少异常,调用者就要处理多少异常,或者继续往上抛出
        
    }
    public static void test() throws FileNotFoundException,NullPointerException,ArithmeticException{//这里可以抛出多个异常
        //这里的异常,我们没有处理,而是抛出给调用者处理
        FileInputStream fis = new FileInputStream("d://aa.txt");//FileNotFoundException是编译异常
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.throws细节

1.对于编译异常,程序中必须处理,比如try-catch或者throws

2.对于运行时异常,程序中如果没有处理,默认就是throws

实例:
public class ThrowsDetails {
    public static void main(String[] args) throws ArithmeticException{//这里是默认抛出的异常,可以不写
        f1();
    }
    public static void f1() throws ArithmeticException{ //这里是默认抛出的异常,可以不写
        int n1 = 10;
        int n2 = 0;
        System.out.println("res=" + (n1 / n2));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.子类重写父类的方法的时候,抛出的异常类型应该与父类的异常类型一致,或者是父类异常类型的子类

实例:
class Father {
    public void method() throws Exception {

    }
}
class son extends Father {
    //子类重写父类的方法时,抛出的异常类型应该和父类的异常类型一致,或者是父类异常类型的子类
    public void method() throws ArithmeticException {

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.throws过程中,如果有方法try-catch,就相当于处理了异常,不需要再抛出异常了

5.当方法抛出的是运行时异常的话调用它的方法可以不处理,但是如果抛出的是编译异常的话,那么调用它的方法就必须处理

class A {
    public void method1() throws FileNotFoundException {
        method();
    }
    public void method() throws FileNotFoundException {//这个方法抛出的是编译异常,所以调用他的方法必须处理

    }
    public void method2() {
        method3();
    }
    public void method3() throws ArithmeticException {//这个方法抛出的是运行时异常,所以调用他的方法可以不处理

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4.throw和throws的区别

  1. throws 异常处理的一种方式,位置是在方法声明处,后面跟的东西是异常类型
  2. throw 手动生成异常的关键字,位置在方法体中,后面跟的东西是具体的异常对象

5.自定义异常类

实例:
public class CustomException {
    public static void main(String[] args) {
        int age = 180;
        if (!(age >= 18 && age <= 120)) {//如果年龄不在18-120之间
            //抛出异常
            throw new AgeException("年龄需要在18-120之间");//抛出了自定义异常,并且调用构造方法,传入message,然后调用父类的构造器,输出message
        }
    }

}
//自定义的异常
class AgeException extends RuntimeException {//继承运行时异常
    public AgeException(String message){
        super(message);//调用父类的构造器,传入message,输出message
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
测试题1:

image-20231107201628784

解释:
  1. 在main方法中首先调用了静态方法methodA(),首先输出“进入方法A”
  2. 然后执行finally输出“用A方法的finally”
  3. 最后抛出异常
  4. 异常被catch捕获后,输出“制造异常”
  5. 执行methodB()方法,输出“进入方法B”
  6. 执行finally,输出“调用B方法的finally”
  7. 返回
测试题2:

image-20231107210615200

代码:
class Homework1 {
    public static void main(String[] args) {
        System.out.println("请输入两个整数:");
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
        try {
            int num1 = Integer.parseInt(str1);
            int num2 = Integer.parseInt(str2);
            double res = Test.cal(num1, num2);
            System.out.println("res=" + res);
        } catch (NumberFormatException e) {
            System.out.println("输入的不是整数");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        }

    }
    }

class Test{
    public static double cal(int num1, int num2) {
        return num1 / num2;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
解释:这里省略了接受命令行参数的部分
测试题3:

image-20231107210737936

答案:
  1. 在args[4]中如果命令行中确实有5个参数那么不会发生异常,如果少于五个则会发生空指针异常
  2. Object o = args[2],String类型向上转型,总是安全的
  3. Integer i = (Integer)o,在上面的o虽然声明的是Object类型,但是实际指向的是String类型的,向向下转型必须要求父类指向的是与子类相同的类型,所以会爆出类型转换异常
测试题4:

image-20231107212457543

答案:
  1. 调用func()方法,先输出一个“B”
  2. 抛出异常,由catch捕获
  3. 输出“C”
  4. 输出“D”
测试题5:

image-20231107212837002

答案:
  1. showExce()抛出Exception异常然后再抛出一个Exception异常
  2. catch捕捉异常,输出“B”
  3. 然后输出“C”
  4. 最后输出“D”
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/228330
推荐阅读
相关标签
  

闽ICP备14008679号