欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

异常处理的那些事——try catch finally、throw、throws\自定义异常

程序员文章站 2022-03-02 21:09:07
...

异常处理相信大家在之前的操作中都有遇见过,本文就异常总涉及到知识点做一总结。

异常概述

运行时异常:程序在运行期间发生的错误。(非受查异常)
编译时异常:在编译时发生异常。(受查异常)

常见的异常类型

NullPointerException (空指针异常)
ArrayIndexOutOfBoundsException(数组角标越界异常)
NumberFormatException (类型转换异常)
ArithmeticException (算数异常)

当然异常的种类有很多在,上述只是列举出几种常见的异常

不处理异常

public static void main(String[] args){
	String str = "lala";
	System.out.println(str + "年龄是:");
	int age = Integer.parseInt("20L");
	System.out.println(age);
}

输出结果
lala年龄是:
Exception in thread "main" java.lang.NumberFormatException: For input string: "20L"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at Test.main(Test.java:15)

我们发现一旦出现异常, 程序就终止了. age 没有正确输出

捕获异常

Java中捕获异常的结构由try catch finally 3部分组成。

基本语法

try{
	可能发生异常的程序
}catch(异常类型 异常对象){
	处理异常
}
finally{
	程序块 
}

:try语句块中的代码如何退出,都将执行finally语句!!!

示例 一:try catch后的执行过程
public static void main(String[] args) {
    int[] arr = {1,2,3,4};
    try{
        System.out.println(arr);
        System.out.println(arr[20]);
        System.out.println("ok");
    }catch(ArrayIndexOutOfBoundsException e){
        e.printStackTrace();
    }
    System.out.println("继续执行");
}

执行结果:
[I@16b98e56
继续执行
java.lang.ArrayIndexOutOfBoundsException: Index 20 out of bounds for length 4
	at Test.main(Test.java:15)

从上边的栗子中可以看出,程序没有因为发生异常而停止执行,而是继续输出之后代码,try语句块中发生了数组角标越界,程序就会调转到catch语句中,并且执行,执行完catch语句中的代码,则继续执行之后的代码。

示例二:catch 只能处理对应种类的异常
public static void main(String[] args) {
    int[] arr = {1,2,3,4};
    try{
        System.out.println(arr);
        arr = null;
        System.out.println(arr[20]);
        System.out.println("ok");
    }catch(ArrayIndexOutOfBoundsException e){
        e.printStackTrace();
    }
}

输出结果:
[I@16b98e56
Exception in thread "main" java.lang.NullPointerException: Cannot load from int array because "arr" is null
	at Test.main(Test.java:17)

此时,catch捕获不到刚才的异常,因为异常类型不匹配

示例三:catch可以有多个
public static void main(String[] args) {

        int[] arr = {1,2,3,4};
        try{
            System.out.println(arr);
            arr = null;
            System.out.println(arr[20]);
            System.out.println("ok");
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("角标越界");
            e.printStackTrace();
        }catch (NullPointerException e){
            System.out.println("空指针");
            e.printStackTrace();
        }
         System.out.println("退出");
    }
}
[I@16b98e56
空指针
退出
java.lang.NullPointerException: Cannot load from int array because "arr" is null
	at Test.main(Test.java:17)

一段代码可能会抛出多种不同的异常, 不同的异常有不同的处理方式.。因此可以搭配多个 catch 代码块。

示例四:使用一个catch捕获所有异常
public static void main(String[] args) {

        int[] arr = {1,2,3,4};
        try{
            System.out.println(arr);
            arr = null;
            System.out.println(arr[20]);
            System.out.println("ok");
        }catch(Exception e){
            e.printStackTrace();
        }
         System.out.println("退出");
    }
}

输出结果:
[I@16b98e56
退出
java.lang.NullPointerException: Cannot load from int array because "arr" is null
	at Test.main(Test.java:17)

Exceptiontry代码块传递给catch代码块的变量类型,e是变量名。catch代码块中的语句e.printStackTrace()`是输出异常的类型、性质、栈层次以及出现在程序中的位置。获取异常的相关信息函数有以下3个:

  1. getMessage()函数:输出错误类型
  2. toString()函数:输出异常的类型与性质
  3. e.printStackTrace():输出异常的类型、性质、栈层次以及出现在程序中的位置

finally语句块

完整的异常处理一定包含finally语句,无论程序中是否有异常,finally语句块必然执行。

finally语句块不执行的特殊情况

  1. 在finally语句块中发生异常
  2. 在前面的代码中使用了System.exit()退出程序
  3. 程序所在的线程死亡
  4. 关闭CPU

自定义异常、throw、throws

在程序中使用自定义异常类,可以分为以下几个步骤:

  1. 创建自定义类
  2. 在方法中通过throw关键字抛出异常对象
  3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句块执行并处理,否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常
  4. 在出现异常方法调用者中捕获并处理异常
    自定义异常通常会继承 Exception 或者 RuntimeException

简单栗子:
实现一个简单的控制台版用户登陆程序, 程序启动提示用户输入用户名密码. 如果用户名密码出错, 使用自定义异常的方式来处理

package Error;
import java.util.Scanner;

class UserError extends Exception{
    public UserError(String message){
        super(message);
    }
}
class PassWordErroe extends Exception{
    public PassWordErroe(String message){
        super(message);
    }
}
public class MyError {
    private static String username= "adime";
    private static String password = "123";

    public static void register(String username, String password) throws UserError,PassWordErroe{
        if(!MyError.username.equals(username)){
            throw new UserError("用户名错误");

        }
        if(!MyError.password.equals(password)){
            throw new PassWordErroe("密码错误");
        }
        System.out.println("登录成功");
    }

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名");
        String user = scanner.nextLine();
        System.out.println("请输入密码");
        String poss = scanner.nextLine();
        try{
            register(user,poss);
        }catch (UserError e){
            e.printStackTrace();
        }catch (PassWordErroe e){
            e.printStackTrace();
        }
        }
    }

一个栗子中涉及到以下知识点:

1、throw关键字抛出异常:

throw关键字常用于方法体中,并且抛出一个异常对象。程序执行到throw语句时终止,后边的语句都不执行。

2、throws关键字抛出异常:

throws关键字通常声明在应用方法时,用来指定方法可能抛出的异常,多个可以使用逗号隔开。

throws将异常抛给上级后,如果不想处理异常,可以继续向上抛,但最终要有处理异常的代码