【Java基础】——深入理解Java异常

1- 什么是异常概述(What、Why)

1-1 什么是异常(What)

基本概念

  • 在 Java 语言中,将程序执行中发生的不正常的情况称为 “异常”。(开发过程中的语法错误和逻辑错误不是异常)

执行过程中的异常可以分为两类

  • Error(错误):Java 虚拟机无法解决的严重问题。比如 JVM 系统内部错误、资源耗尽等情况。比如:StackOverflowError(栈溢出)和 OOM(out of memory),Error 是严重的错误,程序会崩溃。
  • Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等。
    • Exception分为两大类:运行时异常(程序运行时,发生的异常)和 编译时异常(编译时,编译器检查出来的异常)。

通过一个例子,引出异常

public class Exception1 {

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        // 执行到这部分的时候,程序会不出现(抛出异常) ArithmeticException
        // 当抛出异常之后,程序就退出崩溃了,下面的代码就不再执行
        int res = num1/num2;
        System.out.println("程序继续运行...");
    }
}

  • 针对上述问题,执行到 int res = num1/num2;代码的时候,会出现异常。
  • 问题在于出现了一个不算致命的问题,但会导致整个系统崩溃。因此 Java 设计者提供了 异常处理机制来解决这个问题。

1-2 为什么要有异常处理机制(Why)

  • 如果程序员任务一段代码可能出现异常/问题,可以使用 try-catch 异常处理机制来解决。从而保证代码的健壮性。如果进行了异常处理,即使出现了异常,程序可以继续执行。
  • 常见的异常处理机制如下:
public class Exception1 {

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;

        try{
            int res = num1/num2;
        }catch (Exception e){
//            e.printStackTrace();
            System.out.println(e.getMessage()); // 输出异常信息
        }

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

2- ⭐异常体系结构图-总览

2-1 分类

  • 下图的内容需要记忆

  • 编译异常(Checked 受检异常):是在 Java源程序 经过 javac.exe 转为字节码文件阶段遇到的异常。
  • 运行异常(Unchecked 非受检异常):是在字节码文件在内存中加载、运行时类的时候出现的异常。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2-2 异常体系结构小结

异常分为两大类,运行时异常和编译时异常:

  • 运行时异常(Unchecked 非受检异常):编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
    • 举例:(比如除法操作,nums1 = 10nums2 = 0nums1/nums2 可得到运行时异常)
  • 编译时异常(Checked 受检异常):是在 Java源程序 经过 javac.exe 转为字节码文件阶段遇到的异常。
// 编译时异常举例 
public class Exception02 {
    public static void main(String[] args) {
        // Throwable
        FileInputStream fis;
        try {
            fis = new FileInputStream("d:\\aa.jpg");
            int len;
            while ((len = fis.read()) != -1) {
                System.out.println(len);
            }
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 在上述代码中,FileInputStream会报编译时异常,也就是 IDEA 工具会报错,必须立即处理的异常。

3- 五大运行时异常

常见的运行时异常包括

  • NullPointerException :空指针异常
  • ArithmeticException:数学运算异常
  • ArrayIndexOutOfBoundsException:数组下标越界异常
  • ClassCastException:类型转换异常
  • NumberFormatException:数字格式不正确异常

3-1 NullPointerException 空指针异常

NullPointerException 空指针异常

  • 当应用程序试图在需要对象的地方使用 null 时,抛出该异常,看案例演示。
public class NullPointerException_ {
    public static void main(String[] args) {
        String name = null;
        // 在输出的时候会报空指针异常
        System.out.println(name.length()); 
    }
}

3-2 ArithmeticException 算数异常

  • 比如出现 除以 0 的操作的时候就会出现算数异常
public class Exception1 {

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        // 执行到这部分的时候,程序会不出现(抛出异常) ArithmeticException
        // 当抛出异常之后,程序就退出崩溃了,下面的代码就不再执行
        int res = num1/num2;
        System.out.println("程序继续运行...");
    }
}

3-3 ArrayIndexOutOfBoundsException 数组下标越界异常

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

    public static void main(String[] args) {
        int[] nums = new int[4];
        System.out.println(nums[4]);
    }
}

3-4 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 {}

3-5 NumberFormatException 数字格式不正确异常

  • 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 => 使用异常我们可以确保输入是满足条件数字。
  • 例如在使用 Integer.parseInt("你好") 的时候,本来是想将字符串中的数字转为整型,但这个时候就会出现数字格式不正确的异常。
public class NumberFormatException_ {
    public static void main(String[] args) {
        String name = "你好呀";
        // 将String 转成 int
        int num = Integer.parseInt(name); // 抛出NumberFormatException
        System.out.println(num); // 
    }
}

4- 编译异常

  • 编译异常是指,在编译期间就必须处理的异常,否则代码不能通过编译。编译异常常常发生在操作网络、文件、数据库的时候。

常见的编译时异常

  • SQLException:操作数据库时候,查询表可能发生的异常
  • IOException:操作文件时候发生的异常
  • FileNotFoundException:当操作一个不存在的文件时,发生异常
  • ClassNotFoundException:加载类,而文件不存在时,异常
  • EOFException:操作文件,到文件末尾发生异常
  • IllegalArgumentException:参数异常

5- 异常处理机制

异常处理机制就是在发生异常时,对异常处理的方式,主要有两种:

  • try-catch-finally
    • 程序员在代码中捕获发生的异常,自行处理
  • throws
    • 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是 JVM

5-1 try-catch-finally 的处理机制

try-catch-finally 机制:

  • try 中锁放的代码是有可能出现异常的代码,catch 主要是负责捕获异常。
  • 当异常发生的时候,系统将异常封装给 Exception 的对象 e,传递给 catch,当 catch 得到异常对象之后,我们需要自己处理,如果没有发生异常的话 catch 中的代码是不会执行的。
  • finally中的代码部分,无论是否有异常发生,始终是要执行 finally 代码快的(例如对资源释放的代码一般是放在 finally中)
  • 如果没有 finally 也是允许的
try{
    // 有可能有异常的代码
}catch(Exception e){
    // 捕获到异常
    // 1. 当异常发生时
    // 2. 系统将异常封装给 Exception 的对象 e,传递给 catch
    // 3. 得到异常对象之后,程序员自己处理
    // 4. 注意,如果没有发生异常 catch 中的代码块不执行
}finally{
    // 不管 try 中的代码块是否有异常发生,始终要执行 finally 代码块
    // 通常将资源释放的代码,放在 finally 中
}

try-catch 细节

:::info

  • 1) 如果异常发生了,则异常后面的代码不会执行,直接进入到 catch 块
  • 2) 如果异常没有发生,则顺序执行 try 中代码,不会进入到 catch 中
  • 3) 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用 -finally
  • 4) 可以有多个 catch 语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception 在后,NullPointerException 在前),如果发生异常,只会匹配一个catch,案例演示
  • 5) 可以进行 try-finally 配合使用,这种方法相当于没有捕获异常,因此程序会直接崩掉。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
  • 6) 如果在 catch 代码块中有一个临时变量 i,进行了 ++ 操作之后直接 return,此时不会直接返回会等到 finally 的代码执行完成之后才会返回。且 返回的 catch中临时变量结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

:::

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

  • 以下代码块中 System.out.println("数字: " + a); 部分的内容是不会输出的
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());
        }
    }
}

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

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

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

  • 如以下代码,其中 Person 对象有一个空指针异常,和一个算数异常。此时异常的排序需将子类排在前,父类排在后面。
public class TryCatchDetail02 {
    public static void main(String[] args) {
        try {
            Person person = new Person();
            person = null;
            System.out.println(person.toString()); // 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 {
            System.out.println("finally代码块被执行");
        }
    }
}

class Person {
    private String name = "jack";

    public String getName(){
        return name;
    }
}

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


5-2 throws 异常处理机制

JVM 处理异常的机制是,直接输出异常信息 ——> 中断(退出)这个程序

  • 在 Java 中如果对于非受检异常,也就是运行时异常,如果没有显示使用 try-catch 进行异常捕获,此时默认方法会带一个 throws Exception

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

thorws 基本介绍

  • 1)如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
  • 2)在方法声明中用 throws 语句可以声明抛出异常的列表,throws 后面常类型可以是方法中产生的异常类型,也可以是它的父类。
public class Throws01 {
    public static void main(String[] args) {
    }

    public void f2() throws FileNotFoundException {
        // 创建了一个文件流对象
        // 老韩解读:
        // 1. 这里的异常是一个FileNotFoundException 编译异常
        // 2. 使用前面讲过的 try-catch-finally
        // 3. 使用throws,抛出异常,让调用f2方法的调用者(方法)处理
        FileInputStream fis = new FileInputStream("d:/aa.txt");
    }
}

throws 细节

:::info
throws 抛出异常介绍

  • 1) 对于编译异常,程序必须处理,比如 try-catch 或者 throws
  • 2) 对于运行时异常,程序如果没有处理,则默认的就是 throws 方式处理
  • 3) 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
  • 4) 在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必 throws

:::


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

2) 对于运行时异常,程序如果没有处理,则默认的就是 throws 方式处理

3) 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型

class Father { // 父类
    public void method() throws RuntimeException {
    }
}

class Son extends Father { // 子类
    // 3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,
    // 所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常类型的子类型
    @Override
    public void method() throws NullPointerException {
    }
}

5-3 throw 和 throws 的区别

  • thorws 后面跟的是一个具体的异常类型
  • throw 后面跟的是一个具体的异常对象


6- 自定义异常

基本概念

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

6-1 自定义异常步骤

  • 1)定义类:自定义异常类名(程序员自己写)继承 Exception 或 RuntimeException
  • 2)如果继承 Exception ,属于编译异常
  • 3)如果继承 RuntimeException ,属于运行异常(一般来说,继承 RuntimeException)

举例

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

:::info
自定义异常

  • 一般是继承 **RuntimeException** 类,之后通过构造器方法实现自定义异常的信息

:::

public class CustomException {
    public static void main(String[] args) {
        int age = 80;
        // 要求范围在 18 - 120 之间,否则抛出一个自定义异常
        if (!(age >= 18 && age <= 120)) {
            // 通过构造器设置自定义异常信息
            throw new AgeException("年龄需要在 18~120之间");
        }
        System.out.println("你的年龄范围正确。");
    }
}

// 自定义一个异常
class AgeException extends RuntimeException {
    public AgeException(String message) { // 构造器
        super(message);
    }
}

小结

1- 什么是异常?Java 中的异常是如何分类的?

Java基础异常

分析

  • Java异常
  • 思路:Throwable接口有两个子类,分别是 Error 和 Exception。
  • 关键字:Throwable

知识点详解

  • Java中的异常都来自一个接口 Throwable,其中有两个主要的子类。

1- 谈论 Throwable、Exception、Error 三者的关系

  • 一个是 Exception、一个是 Error
    • Error 一般是虚拟机异常,是程序无法干预的一种错误,这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。常见的有 StackOverFlowOutOfMemory
    • Exception 是 Java 的一个异常类,Exception 下的异常主要分为两类,运行时异常和编译时异常。

2- 谈论 Exception 下的分类

Exception类下的异常主要分为两类

  • 运行时异常(Unchecked 非受检异常):编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException 类及它的子类都是运行时异常对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
    • 举例:(比如除法操作,nums1 = 10nums2 = 0nums1/nums2 可得到运行时异常)
  • 编译时异常(Checked 受检异常):是在 Java源程序 经过 javac.exe 转为字节码文件阶段遇到的异常。

回答

:::info
Java中的异常主要都来自于一个 Throwable 接口

  • ①介绍 Error 和 Exception:Throwable 接口下主要有两个类,分别是 Error 和 Exception
    • **Error** 指的是虚拟机异常,是程序无法干预的一种错误。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。常见的有 StackOverFlowOutOfMemory
    • **Exception** 异常是程序本身可以捕获并处理的异常。
  • ② Exception 异常分类,主要分为两种
    • 运行时异常(Unchecked 非受检异常):运行时异常,一般是在 Java 运行的过程中由于编程的逻辑错误而导致的异常,是可以手动处理避免的。java.lang.RuntimeException 类及它的子类都是运行时异常对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
    • 编译时异常(Checked 受检异常):是在 Java源程序 经过 javac.exe 转为字节码文件阶段遇到的异常。这类异常常见的就是在我们写代码过程中 IDEA 会给出的提示,也就是 Java 程序在运行前需要解决的异常,不然 Java 程序不能编译执行。

常见的运行时异常

  • NullPointerException :空指针异常
  • ArithmeticException:数学运算异常
  • ArrayIndexOutOfBoundsException:数组下标越界异常
  • ClassCastException:类型转换异常
  • NumberFormatException:数字格式不正确异常

常见的编译时异常

  • SQLException:操作数据库时候,查询表可能发生的异常
  • IOException:操作文件时候发生的异常
  • FileNotFoundException:当操作一个不存在的文件时,发生异常
  • ClassNotFoundException:加载类,而文件不存在时,异常
  • EOFException:操作文件,到文件末尾发生异常
  • IllegalArgumentException:参数异常

:::


2- 常见的 Exception 有哪些?

Java基础异常

分析

  • Java异常

知识点详解

程序本事可以捕获并且处理的异常就是 Exception 异常,Exception 又分为两类,一种是运行时异常一种是编译时异常

运行时异常

  • 都是 RuntimeException 类及其子类异常,如 NullPointerException (空指针异常)、IndexOutBoundsException(下标越界异常)等,这些异常不是受检异常,程序可以选择捕获处理也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
  • 运行时异常的特点是 Java 编译器不回去检查它,也就是说,当程序中出现这类异常,即使没有用 try-catch 捕获,也没有使用 throws 语句抛出它,也会编译通过。

非运行时异常(编译异常)

  • RuntimeException以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、SQLException 等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

回答

:::info
其中 **Exception** 异常又划分为 编译时异常和运行时异常两种

  • 运行时异常:也就是 **RutimeException** 下的异常,这种异常可以通过 throws 或者 try-catch 的方式手动处理,这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。常见的异常有 NullPointerException (空指针异常)、IndexOutBoundsException(下标越界异常)等。
  • **非运行时异常(编译异常):**也就是 **RutimeException** 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 **IOException****SQLException** 等以及用户自定义的**Exception**异常,一般情况下不自定义检查异常。

常见的运行时异常

  • NullPointerException :空指针异常
  • ArithmeticException:数学运算异常
  • ArrayIndexOutOfBoundsException:数组下标越界异常
  • ClassCastException:类型转换异常
  • NumberFormatException:数字格式不正确异常

常见的编译时异常

  • SQLException:操作数据库时候,查询表可能发生的异常
  • IOException:操作文件时候发生的异常
  • FileNotFoundException:当操作一个不存在的文件时,发生异常
  • ClassNotFoundException:加载类,而文件不存在时,异常
  • EOFException:操作文件,到文件末尾发生异常
  • IllegalArgumentException:参数异常

:::


3- throw 和 throws 有什么区别?

Java基础异常

分析

  • Java异常

知识点详解

  • thorws 后面跟的是一个具体的异常类型
  • throw 后面跟的是一个具体的异常对象


回答

:::info

  • throw:用于抛出一个具体的异常对象。
  • throws:后面跟的是一个具体的异常类型,用于声明该方法可能抛出的异常。子类方法抛出的异常范围更小,或者根本不抛出异常。

:::


4- Error 和 Exception 有什么区别?

Java基础异常

分析

  • Java异常

知识点详解

  • **Error**:JVM 无法解决的严重问题,如栈溢出 StackOverflowError、内存溢出 OOM 等。程序无法处理的错误。
  • **Exception**:其他因为编程错误或偶然的外在因素导致的一般性问题,可以在代码中进行处理。如:空指针异常、数组下标越界等。

回答

:::info

  • **Error**:JVM 无法解决的严重问题,如栈溢出 StackOverflowError、内存溢出 OOM 等。程序无法处理的错误。
  • **Exception**:其他因为编程错误或偶然的外在因素导致的一般性问题,可以在代码中进行处理。如:空指针异常、数组下标越界等。

:::


5- try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

Java基础异常

分析

  • Java异常

知识点详解

  • 会,当 try 和 catch 中有 return 时,finally 仍然会执行。

回答

:::info

  • 会,当 try 和 catch 中有 return 时,finally 仍然会执行。

:::


6- finally 一定会被执行吗?

Java基础异常

**分析 **

  • Java异常

知识点详解

不一定,有以下两种情况 finally 不会被执行:

  • ① 程序未执行到 try 代码块,(比如在执行 finally 之前程序就 exit 退出了)
try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
    // 终止当前正在运行的Java虚拟机
    System.exit(1);
} finally {
    System.out.println("Finally");
}
  • ② 当一个线程在执行 try 语句块或者 catch 语句块时被打断(Interrupted)或者被终止(Killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。

回答

:::info
不一定,有以下两种情况 finally 不会被执行:

  • ① 程序未执行到 try 代码块,(比如在执行 finally 之前程序就 exit 退出了)
  • ② 当一个线程在执行 try 语句块或者 catch 语句块时被打断(Interrupted)或者被终止(Killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。

:::


7- 什么是受检异常(Checked Exception)和非受检异常(Unchecked Exception)?

Java基础异常

**分析 **

  • Java异常

知识点详解

其中 **Exception** 异常又划分为 编译时异常和运行时异常两种

  • 运行时异常(非受检异常):也就是 **RutimeException** 下的异常,这种异常可以通过 throws 或者 try-catch 的方式手动处理,这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。常见的异常有 NullPointerException (空指针异常)、IndexOutBoundsException(下标越界异常)等。
  • **非运行时异常(受检异常):**也就是 **RutimeException** 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 **IOException****SQLException** 等以及用户自定义的**Exception**异常,一般情况下不自定义检查异常。

回答

:::info
其中 **Exception** 异常又划分为 编译时异常和运行时异常两种

  • 运行时异常(非受检异常):也就是 **RutimeException** 下的异常,这种异常可以通过 throws 或者 try-catch 的方式手动处理,这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。常见的异常有 NullPointerException (空指针异常)、IndexOutBoundsException(下标越界异常)等。
  • **非运行时异常(受检异常):**也就是 **RutimeException** 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 **IOException****SQLException** 等以及用户自定义的**Exception**异常,一般情况下不自定义检查异常。

:::


8- 解释 try-catch-finally 语句的工作原理。

Java基础异常

**分析 **

  • Java异常

知识点详解

try 部分的代码

  • 其中 try 中放的代码是可能出现异常的代码块。catch 主要是负责捕获异常。

catch部分

  • 如果 try 部分的代码发生了异常,catch 就负责捕获信息,将异常封装为 Exception 对象。当 catch 得到异常对象之后,我们需要自己处理,如果没有发生异常的话 catch 中的代码是不会执行的。

finally部分

  • finally中的代码部分,无论是否有异常发生,始终是要执行 finally 代码快的(例如对资源释放的代码一般是放在 finally中)如果没有 finally 也是允许的。

try-cath细节

  • 1) 如果异常发生了,则异常后面的代码不会执行,直接进入到 catch 块
  • 2) 如果异常没有发生,则顺序执行 try 中代码,不会进入到 catch 中
  • 3) 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用 -finally
  • 4) 可以有多个 catch 语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception 在后,NullPointerException 在前),如果发生异常,只会匹配一个catch,案例演示
  • 5) 可以进行 try-finally 配合使用,这种方法相当于没有捕获异常,因此程序会直接崩掉。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
  • 6) 如果在 catch 代码块中有一个临时变量 i,进行了 ++ 操作之后直接 return,此时不会直接返回会等到 finally 的代码执行完成之后才会返回。且 返回的 catch中临时变量结果。

回答

:::info
try 部分的代码

  • 其中 try 中放的代码是可能出现异常的代码块。catch 主要是负责捕获异常。

catch部分

  • 如果 try 部分的代码发生了异常,catch 就负责捕获信息,将异常封装为 Exception 对象。当 catch 得到异常对象之后,我们需要自己处理,如果没有发生异常的话 catch 中的代码是不会执行的。

finally部分

  • finally中的代码部分,无论是否有异常发生,始终是要执行 finally 代码快的(例如对资源释放的代码一般是放在 finally中)如果没有 finally 也是允许的。

try-cath细节

  • 1) 如果异常发生了,则异常后面的代码不会执行,直接进入到 catch 块
  • 2) 如果异常没有发生,则顺序执行 try 中代码,不会进入到 catch 中
  • 3) 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用 -finally
  • 4) 可以有多个 catch 语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception 在后,NullPointerException 在前),如果发生异常,只会匹配一个catch,案例演示
  • 5) 可以进行 try-finally 配合使用,这种方法相当于没有捕获异常,因此程序会直接崩掉。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
  • 6) 如果在 catch 代码块中有一个临时变量 i,进行了 ++ 操作之后直接 return,此时不会直接返回会等到 finally 的代码执行完成之后才会返回。且 返回的 catch中临时变量结果。

:::


9- 三道异常处理经典题目,如果 try 中带有 return,finally 怎么执行?

Java基础异常

**分析 **

  • Java异常

知识点详解

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

    public static int test() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.print("3");
        }
    }
}
  • 执行结果:31
  • 解析:trycatchfinally 的基础用法,在 return 前会先执行 finally 的语句块,所以是先输出 finally 里面的 3,再输出1。
public class TryDemo {
    public static void main(String[] args) {
        System.out.println(test1());
    }

    public static int test1() {
        try {
            return 2;
        } finally {
            return 3;
        }
    }
}
  • 执行结果:3
  • 解析:try 返回前先执行 finally,如果 finally 里面不按套路出牌,直接 return 了,自然也就不会走到 try 里面的 return了。
public class TryDemo {
    public static void main(String[] args) {
        System.out.println(test1());
    }

    public static int test1() {
        int i = 0;
        try {
            i = 2;
            return i;
        } finally {
            i = 3;
        }
    }
}
  • 执行结果:2
  • 解析:这段不应该返回 3 吗,其实在实际执行 finally 之前, JVM 会先将 i 的结果暂存起来,然后 finally 执行完成之后,会返回之前存储的结果,而不是返回 i ,所以 i 已经被修改为 3,最终返回的还是之前暂存的结果 2。

回答

:::info

  • 解析:trycatchfinally 的基础用法,在 return 前会先执行 finally 的语句块,所以是先输出 finally 里面的 3,再输出1。

:::

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值