• 36、异常(Exception)


    一、 引入:

    不应该出现了一个不算致命的问题就导致整个系统崩溃,所以java设计者提供了一个异常处理机制来解决问题

    快速入门:

    1. package exception_;
    2. public class Exception01 {
    3. public static void main(String[] args) {
    4. int num1=10;
    5. int num2=0;
    6. //异常处理流程:把该代码块——》选中——》快捷键:ctrl+alt+t——》选择try-catch
    7. //如果进行异常处理,那么即使出现了异常,程序可以继续执行
    8. try {
    9. int res=num1/num2;
    10. } catch (Exception e) {
    11. throw new RuntimeException("出现异常的原因:"+e.getMessage());//e.getMessage()输出异常信息
    12. }
    13. System.out.println("程序继续运行……");
    14. }
    15. }
    16. //输出:
    17. // Exception in thread "main" java.lang.RuntimeException: 出现异常的原因:/ by zero
    18. // at exception_.Exception01.main(Exception01.java:12)

    二、基本介绍:

    1、基本概念:java语言中,将程序执行中发生的不正常情况称为“异常”(开发过程中的语法错误和逻辑错误不是异常)

    2、执行过程中所发生的异常事件可分为两类:

    (1)Error(错误):java虚拟机无法解决的严重问题

    如:JVM系统内部错误、资源耗尽等严重情况,比如:StackOverflowError[栈溢出]和OOM(out of memory),Error是严重错误,程序会崩溃

    (2)Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理

    例如空指针访问,试图读取不存在的文件,网络连接中断等等

    Exception分为两大类:运行时异常[ 程序运行时发生的异常 ]和编译时异常[ 编程时编译器检查出的异常 ]

    1)运行时异常:编译器检查不出来,编译器不要求强制处置的异常,一般是编程时的逻辑错误,是程序员应该避免其出现的异常,java.lang.RuntimeException类及它的子类都是运行时异常

    对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响

    2)编译时异常:编译器要求必须处置的异常(任务不合理,就不干活了)

    进入到Throwable的源码后,把光标放在 Throwable上,右击,选择……

     即可得到……,可以在上面画思维导图(嘿嘿)

     右击,选择“显示实现”

     即可开始添加

     

     三、异常体系图:

    (虚线是实现,实线是继承)

     三、详细介绍:

    1、常见的运行时异常:

    (1)NullPointerException空指针异常

    当应用程序试图在需要对象的地方使用null时,抛出该异常

    1. package exception_;
    2. public class NullPointerException_ {
    3. public static void main(String[] args) {
    4. String name=null;
    5. System.out.println(name.length());
    6. }
    7. }
    8. //输出:
    9. // Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
    10. // at exception_.NullPointerException_.main(NullPointerException_.java:6)

    (2)ArithmeticException数学运算异常

    当出现异常的运算条件时,抛出此异常

    1. package exception_;
    2. public class Exception01 {
    3. public static void main(String[] args) {
    4. int num1=10;
    5. int num2=0;
    6. int res=num1/num2;
    7. System.out.println(res);
    8. }
    9. }
    10. //输出:
    11. // Exception in thread "main" java.lang.ArithmeticException: / by zero
    12. // at exception_.Exception01.main(Exception01.java:7)

    (3)ArrayIndexOutOfBoundsException数组下标越界异常

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

    1. package exception_;
    2. public class ArrayIndexOutOfBoundsException_ {
    3. public static void main(String[] args) {
    4. int[] arr={1,2,4};
    5. for(int i=0;i<=arr.length;i++){
    6. System.out.println(arr[i]);
    7. }
    8. }
    9. }
    10. //输出:
    11. //1
    12. //2
    13. //4
    14. //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    15. // at exception_.ArrayIndexOutOfBoundsException_.main(ArrayIndexOutOfBoundsException_.java:7)

    (4)ClassCastException类型转换异常

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

    1. package exception_;
    2. public class ClassCastException_ {
    3. public static void main(String[] args) {
    4. A b1=new B();//向上转型,b1指向A对象
    5. B b2=(B)b1;//向下转型,b1指向B对象
    6. C c2=(C)b1;//b1不能指向C对象,因为B和C没有关系
    7. }
    8. }
    9. class A{}
    10. class B extends A{};
    11. class C extends A{};
    12. //输出:
    13. // Exception in thread "main" java.lang.ClassCastException: class exception_.B cannot be cast to class exception_.C (exception_.B and exception_.C are in unnamed module of loader 'app')
    14. // at exception_.ClassCastException_.main(ClassCastException_.java:7)

    (5)NumberFormatException数字格式不正确异常

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

    1. package exception_;
    2. public class NumberFormatException_ {
    3. public static void main(String[] args) {
    4. String name="韩顺平";//应该输入数字
    5. int num=Integer.parseInt(name);
    6. System.out.println(num);
    7. }
    8. }
    9. //输出:
    10. // Exception in thread "main" java.lang.NumberFormatException: For input string: "韩顺平"
    11. // at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    12. // at java.base/java.lang.Integer.parseInt(Integer.java:665)
    13. // at java.base/java.lang.Integer.parseInt(Integer.java:781)
    14. // at exception_.NumberFormatException_.main(NumberFormatException_.java:6)

    2、常见的编译异常:

    (1)SQLException,操作数据时,查询表可能发生异常

    (2)IOException,操作文件时,异常

    (3)FileNotFoundException,当操作一个不存在的文件时,异常

    (4)ClassNotFoundException,加载类,而该类不存在时,异常

    (5)EOFException,操作文件,到文件末尾,异常

    (6) IllegalArgumentException,参数异常

    四、异常处理:

    1、异常处理方式:

    (1)try-catch-finally(可以没有finally)

    1)程序员在代码中捕获发生的异常,自行处理(try用于包含可能出错的代码,catch用于处理try块中发生的异常)

    2)

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

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

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

    ·可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子灰异常在前(因为如果父类在前,就可以囊括后面子类的异常处理,那后面子类异常处理的存在也就没有意义了),如果发生异常,只会匹配一个catch

    1. package exception_;
    2. import project20221109.Person;
    3. public class TryCatchDetail02 {
    4. public static void main(String[] args) {
    5. try {
    6. Person_ person=new Person_();
    7. System.out.println(person.getName());//NullPointerException
    8. int num1=10;
    9. int num2=0;
    10. int res=num1/num2;//ArithmeticException
    11. } catch (NullPointerException e) {
    12. System.out.println("空指针异常="+e.getMessage());
    13. }catch (ArithmeticException e){
    14. System.out.println("算术异常="+e.getMessage());
    15. }catch (Exception e){
    16. System.out.println(e.getMessage());
    17. }finally {
    18. }
    19. }
    20. }
    21. class Person_{
    22. private String name;
    23. public String getName() {
    24. return name;
    25. }
    26. }
    27. //输出:
    28. //null
    29. //算术异常=/ by zero

    ·可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉 /退出

    (应用场景:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑)

    1. package exception_;
    2. public class TryCatchDetail03 {
    3. public static void main(String[] args) {
    4. try {
    5. int n1 = 10;
    6. int n2 = 0;
    7. System.out.println(n1 / n2);
    8. } finally {
    9. System.out.println("执行了finally...");
    10. }
    11. System.out.println("程序继续执行...");
    12. }
    13. }
    14. //输出:
    15. // 执行了finally...
    16. //Exception in thread "main" java.lang.ArithmeticException: / by zero
    17. // at exception_.TryCatchDetail03.main(TryCatchDetail03.java:8)
    1. //练习题
    2. class ExceptionExe01{
    3. public static int method(){
    4. int i=1;
    5. try {
    6. i++;
    7. String[] name=new String[3];
    8. if(name[1].equals("tom")){
    9. System.out.println(name[1]);
    10. }else{
    11. name[3]="hspedu";
    12. }
    13. return 1;
    14. } catch (ArrayIndexOutOfBoundsException e) {
    15. return 2;
    16. }catch (NullPointerException e){
    17. return ++i;
    18. //程序执行到这里时i=3,但不会马上返回,因为还有finally没有执行,
    19. //所以用了一个临时变量temp来保存3
    20. } finally{
    21. ++i;
    22. System.out.println("i="+i);
    23. //输出i=4后,因为没有return语句,无法退出程序,又返回上面去返回3
    24. }
    25. }public static void main(String[] args) {
    26. System.out.println(method());
    27. }
    28. }
    29. //输出
    30. //i=4
    31. //3
    1. //题目:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止
    2. //思路:
    3. //1、创建Scanner对象
    4. //2、使用无限循环,去接收一个输入
    5. //3、然后将该输入的值,转成一个int
    6. //4、如果在转换时,抛出异常,说明输入的内容不是一个可以转成int的内容
    7. //5、如果没有抛出异常,则break该循环
    8. package exception_;
    9. import java.util.Scanner;
    10. public class TryCatchDetail04 {
    11. public static void main(String[] args) {
    12. Scanner scanner=new Scanner(System.in);
    13. int num=0;
    14. String inputStr="";
    15. while(true){
    16. System.out.println("请输入一个整数:");
    17. inputStr=scanner.next();
    18. try {
    19. num=Integer.parseInt(inputStr);//这里可能抛出异常k
    20. break;
    21. } catch (NumberFormatException e) {
    22. System.out.println("你输入的不是一个整数:");
    23. }
    24. }
    25. System.out.println("你输入的值是="+num);
    26. }
    27. }
    28. //输出:
    29. //请输入一个整数:
    30. //tom
    31. //你输入的不是一个整数:
    32. //请输入一个整数:
    33. //1
    34. //你输入的值是=1

    (2)throws

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

     如果程序员没有显示是处理异常,则默认是throws

     2)在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类

    1. public void f2() throws FileNotFoundException,NullPointerException,ArithmeticException{}
    2. //也可以写成
    3. public void f2() throws Exception{}

    3)子类重写父类的方法时,对抛出异常的规定:

    子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型(如果子类抛出的异常比父类大,那子类抛完到父类抛出异常时就没有必要抛了)

    1. class Father{
    2. public void method() throws RuntimeException{}
    3. }
    4. class Son extends Father{
    5. public void method() throws ArithmeticException{}
    6. }

    4)在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws

    5)细节:

    1. public static void f1(){
    2. f3();
    3. //报错原因:因为f3()方法抛出的是一个编译异常,即这时f1()必须处理这个编译异常
    4. //方法一:public static void f1() throws FileNotFoundException{}
    5. //方法二:
    6. // try {
    7. // f3();
    8. // } catch (Exception e) {
    9. // throw new RuntimeException(e);
    10. // }
    11. }
    12. public static void f3() throws FileNotFoundException{
    13. FileInputStream fis=new FileInputStream("d://aa.txt");
    14. }
    1. public static void f1(){
    2. f3();//因为f3()抛出的是运行异常,不要求程序员显示处理,因为有默认处理机制
    3. }
    4. public static void f3() throws ArithmeticException{
    5. }

    五、自定义异常

    1、概念:当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这时可以自己设计异常类,用于描述该错误信息

    2、步骤:

    (1)定义类:自己写类名,继承Exception或RuntimeException

    (2)如果继承Exception,属于编译异常

    (3)如果继承RuntimeException,属于运行异常(一般是继承RuntimeException),好处在于可以使用默认的处理机制

    六、throw 和 throws的区别:

    七、练习题

    1. package exception_;
    2. import java.util.Scanner;
    3. public class Homework01 {
    4. public static void main(String[] args) {
    5. try {
    6. if(args.length!=2){
    7. throw new ArrayIndexOutOfBoundsException("参数个数不对");
    8. }
    9. int n1=Integer.parseInt(args[0]);
    10. int n2=Integer.parseInt(args[1]);
    11. double res=cal(n1,n2);
    12. System.out.println("计算结果是:"+res);
    13. } catch (ArrayIndexOutOfBoundsException e) {
    14. System.out.println(e.getMessage());
    15. } catch (NumberFormatException e) {
    16. System.out.println("参数格式不正确,需要输出整数");;
    17. }catch (ArithmeticException e){
    18. System.out.println("出现了除0的异常");
    19. }
    20. }
    21. public static double cal(int n1,int n2){
    22. return n1/n2;
    23. }
    24. }
    25. //在编辑配置处输入
  • 相关阅读:
    Linux Debian下突然所有命令未找到,显示bash: xxxxx: command not found的解决办法
    如何理解BOM(物料清单)在整个生产管理中发挥的作用?
    【RocketMQ集群】Linux搭建RocketMQ双主双从集群
    源码选择指南:比较流行的同城外卖跑腿系统解决方案
    【主流技术】聊一聊消息队列 RocketMQ 的基本结构与概念
    【Spring。。】Day18
    Mysql日志
    STM32G0开发笔记-Platformio平台下使用libopencm3库
    基于Spring的发布订阅模式 EventListener
    《JAVA EE》内部类(上篇)
  • 原文地址:https://blog.csdn.net/weixin_72052233/article/details/127933931