Java - 异常(二)- 异常处理的方式1:捕获异常(try-catch-finally)

2023-12-13 05:11:04

目录

第六章 异常处理

🐶6.1 异常处理概述

🐶6.2 方式1:捕获异常(try-catch-finally)

6.2.1 try-catch-finally基本格式

6.2.2 示例代码

6.2.3 整体执行过程:

6.2.4 开发体会

6.2.5 finally

6.2.6 异常处理的体会

?面试题:final,finally,finalize的区别


第六章 异常处理

Java异常处理的五个关键字:try、catch、finally、throw、throws

🐶6.1 异常处理概述

在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行x/y运算时,要检测分母为0,数据为空,输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿,可读性差,程序员需要花很大的精力“堵漏洞”。因此采用异常处理机制。

Java异常处理

Java采用的异常处理机制,是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护。

Java异常处理的方式:

方式一:try-catch-finally

方式二:throws + 异常类型

🐶6.2 方式1:捕获异常(try-catch-finally)

Java提供了异常处理的抓抛模型

  • 前面提到,Java程序的执行过程中如出现异常,会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。

  • 如果一个方法内抛出异常,该异常对象会被抛给调用者方法中处理。如果异常没有在调用者方法中处理,它继续被抛给这个调用方法的上层方法。这个过程将一直继续下去,直到异常被处理。这一过程称为捕获(catch)异常。

  • 如果一个异常回到main()方法,并且main()也不处理,则程序运行终止。

6.2.1 try-catch-finally基本格式

捕获异常语法如下:

try{
        ......        //可能产生异常的代码
}
catch( 异常类型1 e ){
        ......        //当产生异常类型1型异常时的处置措施
}
catch( 异常类型2 e ){
        ......         //当产生异常类型2型异常时的处置措施
}  
finally{
        ...... //无论是否发生异常,都无条件执行的语句
} 
6.2.2 示例代码
import java.sql.SQLOutput;
import java.util.Date;
import java.util.InputMismatchException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args)  throws Exception{
        try{
            Scanner scanner=new Scanner(System.in);
            int num=scanner.nextInt();
            System.out.println(num);
        }catch(InputMismatchException e){
            System.out.println("出现了InputMismatchException的异常");
        }
        System.out.println("异常处理结束,代码继续执行");
        
    }
}

结果:

6.2.3 整体执行过程:

当某段代码可能发生异常,不管这个异常是编译时异常(受检异常)还是运行时异常(非受检异常),我们都可以使用try块将它括起来,并在try块下面编写catch分支尝试捕获对应的异常对象。

  • 如果在程序运行时,try块中的代码没有发生异常,那么catch所有的分支都不执行。

  • 如果在程序运行时,try块中的代码发生了异常,根据异常对象的类型,将从上到下选择第一个匹配的catch分支执行。此时try中发生异常的语句下面的代码将不执行,而整个try...catch之后的代码可以继续运行。

  • 如果在程序运行时,try块中的代码发生了异常,但是所有catch分支都无法匹配(捕获)这个异常,那么JVM将会终止当前方法的执行,并把异常对象“抛”给调用者。如果调用者不处理,程序就挂了。

2、try

  • 捕获异常的第一步是用try{…}语句块选定捕获异常的范围,将可能出现异常的业务逻辑代码放在try语句块中。

3、catch (Exceptiontype e)

  • catch分支,分为两个部分,catch()中编写异常类型和异常参数名,{}中编写如果发生了这个异常,要做什么处理的代码。

  • 如果明确知道产生的是何种异常,可以用该异常类作为catch的参数;也可以用其父类作为catch的参数。

比如:可以用ArithmeticException类作为参数的地方,就可以用RuntimeException类作为参数,或者用所有异常的父类Exception类作为参数。但不能是与ArithmeticException类无关的异常,如NullPointerException(catch中的语句将不会执行)。

  • 每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。

  • 如果有多个catch分支,并且多个异常类型有父子类关系,必须保证小的子异常类型在上,大的父异常类型在下。否则,报错。

?catch中常用异常处理的方式

  • 自己编写输出的语句

  • public String getMessage():获取异常的描述信息,返回字符串

  • public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。包含了异常的类型、异常的原因、还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace()。

6.2.4 开发体会

1. 对于运行时异常

开发中,通常就不进行显示的处理了

一旦在程序执行中,出现了运行时异常,那么就根据异常的提示信息修改代码即可。

2. 对于编译时异常

一定要处理,否则编译不通过

6.2.5 finally

1. 概念

我们将一定要被执行的代码声明在finally结构中

更深刻的理解:无论try中或catch中是否存在仍未被处理的异常,无论try中或catch中是否return语句等,finally中声明的语句都一定要被执行。

2. 代码示例

🧀代码示例1:

import java.sql.SQLOutput;
import java.util.Date;
import java.util.InputMismatchException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args)  throws Exception{
        int result=test("a");
        System.out.println(result);

    }
    public static int test(String str){
        try{
            Integer.parseInt(str);
            return 1;
        }catch (NumberFormatException e){
            return -1;
        }finally {
            System.out.println("test结束");
        }
    }
}

结果:

🧀代码示例2:

import java.sql.SQLOutput;
import java.util.Date;
import java.util.InputMismatchException;
import java.util.Scanner;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args)  throws Exception{
        int result=test("a");
        System.out.println(result);

    }
    public static int test(String str){
        try{
            Integer.parseInt(str);
            return 1;
        }catch (NumberFormatException e){
            return -1;
        }finally {
            System.out.println("test结束");
            return 0;
        }
    }
}

?结果:

?

?🧀代码示例3:

public class Main {
    public static void main(String[] args)  throws Exception{
        int result=test(10);
        System.out.println(result);

    }
    public static int test(int num){
        try{
            return num;
        }catch (NumberFormatException e){
            return num--;
        }finally {
            System.out.println("test结束");
            return ++num;
        }
    }
}

结果:

3. finally使用及举例

  • 因为异常会引发程序跳转,从而会导致有些语句执行不到。而程序中有一些特定的代码无论异常是否发生,都需要执行。什么时候的代码必须最终执行?

??????????当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。

??????????这样的代码通常就会放到finally块中。所以,我们通常讲一定要执行的代码声明在finally中。

  • 唯一的例外,使用System.exit(0)来终止当前正在运行的Java虚拟机。

  • finally语句和catch语句是可选的,但finally不能单独使用。

try{
     
}finally{
    
} 
6.2.6 异常处理的体会
  • 前面使用的异常都是RuntimeException类或是它的子类,这些类的异常的特点是:即使没有try和catch捕获,java自己也能捕获,并且编译通过(但运行时会发生异常使得程序运行终止)。所以,对于这类异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。

  • 如果抛出的异常是IOException等类型的非运行时异常,则必须捕获,否则编译错误。也就是说,我们必须处理编译时异常,将异常进行捕捉,转化为运行时异常。

?面试题:final,finally,finalize的区别

  1. final代表最终,当final用来修饰类时,代表这个类为最终类,不可以被继承。当final用来修饰变量时,代表这个变量为常量,不可以被修改;当final用来修饰方法时,该方法不可以被重写。

  2. finally用于抛异常,finally代码块内语句无论是否发生异常,都会执行。通常用于一些流的关闭。

  3. finalize方法用于垃圾回收。一般情况下不需要我们实现finalize,当对象被回收的时候需要释放一些资源,比如socket链接,在对象初始化时创建,整个生命周期内有效,那么需要实现finalize方法,关闭这个链接。

但是当finalize方法后,并不意味着gc会立即回收该对象,所以有可能等真正调用的时候,对象又不需要回收了,然后到了真正要回收的时候,因为之前调用过一次,这次又不会调用了,产生问题。所以,不推荐使用finalize方法。

文章来源:https://blog.csdn.net/weixin_40968325/article/details/134959582
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。