Java中的异常

目录

引言

基本语法

1. 程序中不处理异常的情况

2. 使用try ..catch ..处理异常

3. Java中一切都是类,异常其实也是类,因此Catch代码块只能捕获相应的异常"类型"

4. 关于错误"堆栈"信息

5. 关于finally代码块:无论是否有异常产生,最终都会执行finally代码块中的代码

6. 异常的处理流程

7. throws和throw关键字——人为抛出异常 

7.1 throws的使用

7.2 throw的使用

异常体系:JDK内部异常的继承关系

1. 非受查异常

a. RuntimeException(运行时异常,编译阶段不报错,运行时出错)。

b. Error——程序内部错误。

2. 受查异常

3. 自定义异常


引言

异常:程序没按照预计的结果运行,在运行的过程中发生了"错误"。

//除0异常
    System.out.println(10 / 0);
//运行错误
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at ExceptionTest.main(ExceptionTest.java:9)
// 数组越界异常
    int[] data = new int[]{1, 3, 5};
    System.out.println(data[10]);
//运行错误
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
	at ExceptionTest.main(ExceptionTest.java:14)

基本语法

异常的基本语法:

try{
    //可能会产生异常的代码,除0,数组越界,空指针等
}[catch 可能出现异常的类型异常对象引用] {
    //出现异常以后如何处理
}[finally] {
    //异常的出口,最终会执行的代码块
    //无论是否有异常产生都会执行的代码块,资源类的释放,文件的关闭等
}

1. 程序中不处理异常的情况

int[] date = {1,2,3};
System.out.println("before...");
System.out.println(date[100]);    //发生异常之后的代码就不再执行
System.out.println("after...");
//输出结果
before...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
	at ExceptionTest.main(ExceptionTest.java:18)

发生异常之后的代码就不再执行

2. 使用try ..catch ..处理异常

int[] date = {1,2,3};
System.out.println("before...");
try {
    //可能会产生异常的代码
    System.out.println(date[100]);
    System.out.println("try中的其他代码块");
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("异常产生了");
}
System.out.println("after...");
//输出结果
before...
异常产生了
after...

一旦try中出现异常,那么try 代码块中的程序就不会继续执行,而是交给catch中的代码来执行。catch执行完毕会继续往下执行。

3. Java中一切都是类,异常其实也是类,因此Catch代码块只能捕获相应的异常"类型"

数组越界异常


此时代码出错的原因在于空指针异常,不属于数组越界异常,因此catch代码块无法处理,所以需要多个catch代码块。

空指针异常被捕获。


有一个异常类是所有异常类的父类——Exception类
我们如果catch块中捕获的是Exception这个类型,就可以接收到所有异常类型。(不推荐)

    public static void main(String[] args) {
        int[] date = {1, 2, 3};
        date = null;
        System.out.println("before...");
        try {
            //可能会产生异常的代码
            System.out.println(date[1]);
            System.out.println("try中的其他代码块");
        } catch (Exception e) {
            System.out.println("异常产生了");
        }
        System.out.println("after...");

    }
//输出结果
before...
异常产生了
after...

若此时明确知道try中可能产生的异常类型,如:数组越界,空指针,catch捕获明确的相关类型。
若此时不太清楚可能产生哪些异常,就使用Exception共同的父类。所有异常的子类都会向上转型变为Exception的引用。

4. 关于错误"堆栈"信息

在Java中其实出现问题是很好解决,异常的错误信息非常完善,到底在哪一行出了怎样的错误,说的非常清楚。

输出程序出现异常的位置以及原因,就调用异常对象的printStackTrace()方法

5. 关于finally代码块:无论是否有异常产生,最终都会执行finally代码块中的代码

 5.1 有异常

    public static void main(String[] args) {
        int[] date = {1, 2, 3};
        try {
            System.out.println(date[100]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally代码块");
        }
    System.out.println("异常体系之后的代码");
    }
//输出结果
java.lang.ArrayIndexOutOfBoundsException: 100
	at exception_test.FinallyTest.main(FinallyTest.java:13)
finally代码块
异常体系之后的代码

5.2 无异常

    public static void main(String[] args) {
        int[] date = {1, 2, 3};
        try {
            System.out.println(date[1]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally代码块");
        }
        System.out.println("异常体系之后的代码");
    }
//输出结果
2
finally代码块
异常体系之后的代码

一般来说资源的释放,方法的关闭操作都在finally代码块中。
比如关闭数据库的连接,关闭文件的操作都在finally代码块中,无论是否有异常产生,都能保证资源会正确释放。


不要在finally代码块中写返回值。

问题:求返回值?

    public static void main(String[] args) {
        int ret = test();
        System.out.println(ret);
    }

    private static int test() {
        try {
            int[] date = {1, 2, 3};
            date[100] = 10;
            return 10;
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            return 20;
        } finally {
            System.out.println("finally代码块");
            return 30;
        }
    }

答:finally是最终都会执行的代码块,若finally中存在返回值,会覆盖掉try或者catch的返回值。

去掉finally的return语句

6. 异常的处理流程

异常处理流程
1. 程序先执行try中的代码
2. 如果try中的代码出现异常,就会结束try 中的代码,看和catch 中的异常类型是否匹配。

        a. 如果找到匹配的异常类型,就会执行catch中的代码。
        b. 如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。
3. 无论是否找到匹配的异常类型。 finally 中的代码都会被执行到(在该方法结束之前执行)。如果上层调用者也没有处理的了异常,就继续向上传递。
4. 一直到 main方法也没有合适的代码处理异常,就会交给JVM来进行处理,此时程序就会异常终止。

7. throws和throw关键字——人为抛出异常 

throws:用在方法声明上,表示该方法可能会产生的异常类型,但是本方法中不处理该异常。若异常产生抛回给调用者

throw:用在方法内部,表示人为产生异常对象并抛出。
异常对象的产生都是发生异常后由JVM产生的,若需要人为产生异常对象,就使用throw关键字。

7.1 throws的使用


7.2 throw的使用

关于这两个关键字的使用,需要结合自定义的异常类来使用。

异常体系:JDK内部异常的继承关系

Java中的异常分为两大类,一类称之为"受查异常",另—类称为"非受查异常"。

1. 非受查异常

上图中蓝色部分的类——非受查异常

RuntimeException以及其子类包括Error及其子类称之为非受查异常,编译阶段可以不显示进行异常处理(try...catch/throws抛出)。

a. RuntimeException(运行时异常,编译阶段不报错,运行时出错)。

其子类有:

ArrayIndexOfBoundsException——数组越界异常;

NullPointerException——空指针异常;

ClassCastException——类型转换异常。


b. Error——程序内部错误。

一般来说,出现这种错误,程序没法再正常执行下去的,只能退出程序。

OutofMemoryError——堆内存溢出错误、StackOverflowError——栈溢出错误。

2. 受查异常

除了这些非受查异常以外的其他异常类属于受查异常,必须在编译阶段显示进行异常的处理,否则编译就会出错。上图中红色部分的类,受查异常。 

受查异常,调用者就必须显示进行异常的处理。



显示处理:

1. 进行try..catch..捕获这个异常


2. 调用者也使用throws向上抛出异常

3. 自定义异常

JDK内部已经帮我们提前定义好了很多的异常类,但是在某些业务场景下,出现的错误需要我们自定义异常类(用户登录的时候,用户名不对,密码不对,这种错误就需要我们来自定义异常类)。

自定义异常类操作简单,只需要继承相关的两个父类就可以。
若希望这个异常必须显示处理——继承Exception父类
若这个异常不需要显示处理——继承RunTimeException父类

package exception_test;
import java.util.Scanner;

public class MyExceptionTest {
    private static String USER_NAME = "小明";
    private static String PASSWORD = "123";

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String userName = scanner.nextLine();
        System.out.println("请输入密码:");
        String pass = scanner.nextLine();
        if (!userName.equals(USER_NAME)) {
            //用户名错误,抛出异常
            throw new UserNameException("用户名错误");
        }
        if (!pass.equals(PASSWORD)) {
            //密码错误,抛出异常
            throw new PassWordException("密码错误");
        }
    }
}

class UserNameException extends RuntimeException {
    public UserNameException(String msg) {
        super(msg);
    }
}

class PassWordException extends RuntimeException {
    public PassWordException(String msg) {
        super(msg);
    }
}

异常体系:
1. try...catch...finally的使用流程
2. 受查和非受查异常的关系以及常见异常
运行时异常就是非受查异常的一种,空指针、数组越界、类型转换。

IOException就是受查异常的一种。
3. throws和throw关键字的使用以及自定义异常类 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瘦皮猴117

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值