关于后端:Java异常Exception详解

3次阅读

共计 8696 个字符,预计需要花费 22 分钟才能阅读完成。

疾速入门

将可能出现异常的代码块选中 -> 快捷键 ctrl + alt + t -> 选中 try-catch

package com.hspedu.exception_;

public class Exception01 {public static void main(String[] args)  {
        int num1 = 10;
        int num2 = 0;//Scanner();
        //2. 当执行到 num1 / num2 因为 num2 = 0, 程序就会呈现 (抛出) 异样 ArithmeticException
        //3. 当抛出异样后,程序就退出,解体了, 上面的代码就不再执行
        //4. 不应该呈现了一个不算致命的问题就导致整个零碎解体
        //5. java 设计者,提供了一个叫异样解决机制来解决该问题
        // 如果程序员,认为一段代码可能出现异常 / 问题,能够应用 try-catch 异样解决机制来解决,从而保障程序的健壮性
        // 将该代码块 -> 选中 -> 快捷键 ctrl + alt + t -> 选中 try-catch
        //6. 如果进行异样解决,那么即便呈现了异样,程序能够继续执行
        try {int res = num1 / num2;} catch (Exception e) {//e.printStackTrace();
            System.out.println("出现异常的起因 =" + e.getMessage());// 输入异样信息
        }

        System.out.println("程序持续运行....");

    }
}

异样介绍

Java 语言中,将程序执行中产生的不失常状况称为“异样”。(开发过程中的语法错误和逻辑谬误不是异样)

执行过程中所产生的异样事件可分为两大类:

1.Error(谬误):Java 虚拟机无奈解决的重大问题。如:JVM 零碎外部谬误、资源耗尽等重大状况。比方: StackOverflowError[栈溢出] 和 OOM(out of memory).

Error 是严重错误, 程序会解体。

2.Exception: 其它因编程谬误或偶尔的外在因素导致的一般性问题,能够应用针对性的代码进行解决。例如空指针拜访,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:

  • 运行时异样[程序运行时,产生的异样]
  • 编译时异样[编程时, 编译器查看出的异样]

异样体系图一览!

异样体系图

异样体系图的小结

  1. 异样分为两大类,运行时异样和编译时异样.
  2. 运行时异样,编译器查看不进去。个别是指编程时的逻辑谬误,是程序员应该防止其呈现的异样。java.lang.RuntimeException 类及它的子类都是运行时异样。
  3. 对于运行时异样,能够不作解决,因为这类异样很广泛,若全解决可能会对程序的可读性和运行效率产生影响。
  4. 编译时异样,是编译器要求必须处理的异样。

常见的运行时异样

常见的运行时异样包含

1) NullPointerException 空指针异样
2) ArithmeticException 数学运算异样
3) ArrayIndexOutOfBoundsException 数组下标越界异样
4) ClassCastException 类型转换异样
5) NumberFormatException 数字格局不正确异样[]

常见的运行时异样举例

  1. NullPointerException 空指针异样
    当应用程序试图在须要对象的中央应用 null 时,抛出该异样。

    public class NullPointerException_ {public static void main(String[] args) {
    
       String name = null; // 空指针出现异常
       System.out.println(name.length());
     }
    }
  2. ArithmeticException 数学运算异样

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

3) ArrayIndexOutOfBoundsException 数组下标越界异样
用非法索引拜访数组时抛出的异样。如果索引为负或大于等于数组大小,则该索引为非法索引。

  1. ClassCastException 类型转换异样
    当试图将对象强制转换为不是实例的子类时,抛出该异样。例如,以下代码将生成一个ClassCastException

    public class ClassCastException_ {public static void main(String[] args) {A b = new B(); // 向上转型
       B b2 = (B)b;// 向下转型,这里是 OK
       C c2 = (C)b;// 这里抛出 ClassCastException
     }
    }
    class A {}
    class B extends A {}
    class C extends A {}
  2. NumberFormatException 数字格局不正确异样
    当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格局时,抛出该异样 => 应用异样咱们,能够确保输出是满足条件数字.

    public class NumberFormatException_ {public static void main(String[] args) {
       String name = "timerring";
       // 将 String 转成 int
       int num = Integer.parseInt(name); // 抛出 NumberFormatException
       System.out.println(num);
     }
    }

编译异样

编译异样是指在编译期间,就必须解决的异样,否则代码不能通过编译。

常见的编译异样

SQLException:操作数据库时,查问表可能产生异样

IOException:操作文件时,产生的异样

FileNotFoundException:当操作一个不存在的文件时,产生异

ClassNotFoundException:加载类, 而该类不存在时,异样

EOFException:操作文件, 到文件开端, 产生异样

lllegalArguementException:参数异样

异样解决

根本介绍

异样解决就是当异样产生时,对异样解决的形式。

异样解决的形式

1) try-catch-finally:程序员在代码中捕捉产生的异样,自行处理

2) throws:将产生的异样抛出,交给调用者 (办法) 来解决, 最顶级的解决者就是 JVM。

示意图

如果程序员没有显示地解决异样,则默认是 throws。

try-catch 异样解决

try-catch 形式解决异样阐明

  1. Java 提供 try 和 catch 块来解决异样。try 块用于蕴含可能出错的代码。catch 块用于解决 try 块中产生的异样。能够依据须要在程序中有多个 try…catch 块。
  2. 根本语法

    try {
     // 可疑代码
     // 将异样生成对应的异样对象, 传递给 catch 块
    }catch(异样){// 对异样的解决}
    // 如果没有 finally,语法是能够通过

try-catch 形式解决异样细节

  1. 如果异样产生了,则异样产生前面的代码不会执行,间接进入到 catch 块。
  2. 如果异样没有产生,则程序执行 try 的代码块,不会进入到 catch。
  3. 如果心愿不论是否产生异样,都执行某段代码 (比方敞开连贯, 开释资源等)
    则应用如下代码 finally {}
  4. 能够有多个 catch 语句,捕捉不同的异样 (进行不同的业务解决),要求父类异
    常在后,子类异样在前,比方 (Exception 在后,NullPointerException 在前),如果产生异样,只会匹配一个 catch。(因为如果在后面都让Exception 捕捉了,前面写子类捕捉就没有用了)。

    package com.hspedu.try_;
    
    public class TryCatchDetail02 {public static void main(String[] args) {
            
            //1. 如果 try 代码块有可能有多个异样
            //2. 能够应用多个 catch 别离捕捉不同的异样,相应解决
            //3. 要求子类异样写在后面,父类异样写在前面
            try {Person person = new Person();
                //person = null;
                System.out.println(person.getName());//NullPointerException
                int n1 = 10;
                int n2 = 0;
                int res = n1 / n2;//ArithmeticException
            } catch (NullPointerException e) {System.out.println("空指针异样 =" + e.getMessage());
            } catch (ArithmeticException e) {System.out.println("算术异样 =" + e.getMessage());
            } catch (Exception e) {System.out.println(e.getMessage());
            } finally {}}
    }
    
    class Person {
        private String name = "jack";
        public String getName() {return name;}
    }
  5. 能够进行 try-finally 配合应用, 这种用法相当于没有捕捉异样,因而程序会
    间接崩掉 / 退出。利用场景就是执行一段代码,不论是否产生异样,都必须执行某个业务逻辑。

    public class TryCatchDetail03 {public static void main(String[] args) {
            /*
            能够进行 try-finally 配合应用, 这种用法相当于没有捕捉异样,因而程序会间接崩掉 / 退出。利用场景,就是执行一段代码,不论是否产生异            常,都必须执行某个业务逻辑
             */
            try{
                int n1 = 10;
                int n2 = 0;
                System.out.println(n1 / n2);
            }finally {System.out.println("执行了 finally.."); // 执行完间接退出
            }
            System.out.println("程序继续执行.."); // 不会执行
        }
    }

练习

package com.hspedu.try_;

public class TryCatchExercise01 {
}

class Exception01 {public static int method() {
        try {String[] names = new String[3];//String[]数组
            if (names[1].equals("tom")) {//NullPointerException
                System.out.println(names[1]);
            } else {names[3] = "hspedu";
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {return 2;} catch (NullPointerException e) {// 捕捉
            return 3; // 然而不从这里返回
        } finally {  // 必须执行,相当于没有异样捕捉
            return 4; // 返回 4
        }
    }

    public static void main(String[] args) {System.out.println(method()); // 输入 4
    }
}
package com.hspedu.try_;

public class TryCatchExercise03 {
}

class ExceptionExe01 {public static int method() {
        int i = 1;//i = 1
        try {
            i++;// i=2
            String[] names = new String[3];
            if (names[1].equals("tom")) { // 空指针
                System.out.println(names[1]);
            } else {names[3] = "hspedu";
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {return 2;} catch (NullPointerException e) {return ++i;  // i = 3 => 保留长期变量 temp = 3;} finally {
            ++i; //i = 4
            System.out.println("i=" + i);// i = 4
        }
    }

    public static void main(String[] args) {System.out.println(method());// 3
    }
}
// 最终输入 i = 4    3

try-catch-finally 执行程序小结

1) 如果没有出现异常,则执行 try 块中所有语句,不执行 catch 块中语句,如果有 finally,最初还须要执行 finally 外面的语句。
2) 如果出现异常,则 try 块中异样产生后,try 块剩下的语句不再执行。将执行 catch 块中的语句,如果有 finally,最初还须要执行 finally 外面的语句。

课后练习题

如果用户输出的不是一个整数,就提醒他重复输出,直到输出一个整数为止

package com.hspedu.try_;

import java.util.Scanner;

public class TryCatchExercise04 {public static void main(String[] args) {

        // 如果用户输出的不是一个整数,就提醒他重复输出,直到输出一个整数为止
        // 思路
        //1. 创立 Scanner 对象
        //2. 应用有限循环,去接管一个输出
        //3. 而后将该输出的值,转成一个 int
        //4. 如果在转换时,抛出异样,阐明输出的内容不是一个能够转成 int 的内容
        //5. 如果没有抛出异样,则 break 该循环
        Scanner scanner = new Scanner(System.in);
        int num = 0;
        String inputStr = "";
        while (true) {System.out.println("请输出一个整数:"); //
            inputStr = scanner.next();
            try {num = Integer.parseInt(inputStr); // 这里是可能抛出异样
                break;
            } catch (NumberFormatException e) {System.out.println("你输出的不是一个整数:");
            }
        }

        System.out.println("你输出的值是 =" + num);
    }
}

throws 异样解决

根本介绍

1) 如果一个办法 (中的语句执行时) 可能生成某种异样,然而并不能确定如何解决这种异样,则此办法应 显示地申明抛出异样,表明该办法将不对这些异样进行解决,而由该办法的调用者负责解决
2) 在办法申明中用 throws 语句能够申明抛出异样的列表,throws 前面的异样类型能够是办法中产生的异样类型, 也能够是它的父类。

疾速入门案例

throws 前面的异样类型能够是办法中产生的异样类型(也能够是异样列表,抛出多个异样),也能够是它的父类(例如 Exception)。

package com.hspedu.throws_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Throws01 {public static void main(String[] args) { }

    public void f2() throws FileNotFoundException,NullPointerException,ArithmeticException {
        // 创立了一个文件流对象
        //1. 这里的异样是一个 FileNotFoundException 编译异样
        //2. 应用后面讲过的 try-catch-finally
        //3. 应用 throws , 抛出异样, 让调用 f2 办法的调用者 (办法) 解决
        //4. throws 前面的异样类型能够是办法中产生的异样类型,也能够是它的父类(例如 Exception)
        //5. throws 关键字后也能够是 异样列表, 即能够抛出多个异样
        FileInputStream fis = new FileInputStream("d://aa.txt");

    }
}

注意事项和应用细节

  1. 对于编译异样, 程序中必须解决,比方 try-catch 或者 throws。
  2. 对于运行时异样,程序中如果没有解决, 默认就是 throws 的形式解决(相当于办法后有一个 throws XXXException,这时逐级向上,最初 main 办法上可能也默认 throws,这时就给 JVM 解决)。
  3. 子类重写父类的办法时,对抛出异样的规定:子类重写的办法,所抛出的异样类型要么和父类抛出的异样统一,要么为父类抛出的异样的类型的子类型。
  4. 在 throws 过程中,如果有办法 try-catch,就相当于解决异样,就能够不用 throws。

    例如子类有一个编译异样,应用 throws 抛出,那么父类也必须对该异样做出反馈,或是 throws,或者 try catch,否则同样是编译异样。

自定义异样

基本概念

当程序中呈现了某些“谬误”,但该错误信息并没有在 Throwable 子类中形容解决,这个时候能够本人设计异样类, 用于形容该错误信息。

自定义异样的步骤

1) 定义类: 自定义异样类名 (程序员本人写) 继承 Exception 或 RuntimeException

  • 如果继承 Exception,属于编译异样
  • 如果继承 RuntimeException,属于运行异样(一般来说, 继承 RuntimeException)

自定义异样的利用实例

当咱们接管 Person 对象年龄时,要求范畴在 18-120 之间, 否则抛出一个自定义异样(要求继承 RuntimeException),并给出提示信息。

package com.hspedu.customexception_;

public class CustomException {
    // 办法申明处,throws 异样
    public static void main(String[] args) /*throws AgeException*/ {

        int age = 180;
        // 要求范畴在 18 – 120 之间,否则抛出一个自定义异样
        if(!(age >= 18 && age <= 120)) {
            // 这里咱们能够通过结构器,设置信息
            // 在办法体中,这里 throw 对象
            throw new AgeException("年龄须要在 18~120 之间");
        }
        System.out.println("你的年龄范畴正确.");
    }
}
// 自定义一个异样
// 1. 个别状况下,咱们自定义异样是继承 RuntimeException
// 2. 即把自定义异样做成 运行时异样,益处是咱们能够应用默认的解决机制,即主动向上 throws 异样,否则 main 中也得加 throws。class AgeException extends RuntimeException {public AgeException(String message) {// 结构器
        super(message); // 调用父结构器,能够进入源码逐级查看。}
}

父结构器:

    public Throwable(String message) {fillInStackTrace();
        detailMessage = message; // 传入 detailmessage
    }

throw 和 throws 的区别

练习

编程题

编写应用程序,接管命令行的两个参数(整数),计算两数相除。

计算两个数相除,要求应用办法 cal(int n1, int n2)

对数据格式不正确(NumberFormatException)、短少命令行参数(ArrayIndexOutOfBoundsException)、除 0 进行异样解决(ArithmeticException)。

package com.hspedu.homework;

public class Homework01 {public static void main(String[] args) {
        /*
        编写应用程序 EcmDef.java,接管命令行的两个参数(整数),计算两数相除。计算两个数相除,要求应用办法 cal(int n1, int n2)
        对数据格式不正确(NumberFormatException)、短少命令行参数(ArrayIndexOutOfBoundsException)、除 0 进行异样解决(ArithmeticException)。*/

        try {
            // 先验证输出的参数的个数是否正确 两个参数
            if(args.length != 2) {throw new ArrayIndexOutOfBoundsException("参数个数不对");
            }

            // 先把接管到的参数,转成整数
            int n1 = Integer.parseInt(args[0]);
            int n2 = Integer.parseInt(args[1]);

            double res = cal(n1, n2);// 该办法可能抛出 ArithmeticException
            System.out.println("计算结果是 =" + res);

        } catch (ArrayIndexOutOfBoundsException e) {System.out.println(e.getMessage());
        } catch (NumberFormatException e) {System.out.println("参数格局不正确,须要输入整数");
        } catch (ArithmeticException e) {System.out.println("呈现了除 0 的异样");
        }


    }
    // 编写 cal 办法,就是两个数的商
    public static double cal(int n1, int n2) {return n1 / n2;}
}

文章和代码曾经归档至【Github 仓库:https://github.com/timerring/java-tutorial】或者公众号【AIShareLab】回复 java 也可获取。

正文完
 0