Java中的异常

一. 异常原因

异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。

异常发生的原因有很多,一般包括以下几类:

  1. 用户输入非法数据
  2. 要打开的文件不存在
  3. 网络通信时连接中断或者JVM内存溢出

这些异常有的是程序错误引起的,有的是用户错误引起的吗,还有其他一些物理错误引起的。

二. 异常类型

类关系图如下:

Exception和Error类均是Throwable 类的子类。

异常一般分为3类:

  1. 检查性异常。 程序员无法预测,在编译时检查出来。如:用户错误或问题 引起的异常,打开一个不存在的文件。
  2. 运行时异常。 在编译时被忽略。
  3. 错误 。脱离程序员控制的问题,如栈溢出。

1. 错误-Error

用来指示运行时环境发生的错误。例如,JVM 内存溢出。一般地,程序不会从错误中恢复。

2. Exception类的层次

Exception是使用者发现的异常,Java 程序通常不捕获Error。Error一般发生在严重故障时,它们在Java程序处理的范畴之外。Exception可以范围两类,检查异常和非检查异常。

  • 一类是检查型异常/IOException(I/O 输入输出异常)。在Java中所有非 RuntimeException派生的Exception类都是检查型异常,其中 IOException 及其子类异常又被称作「受查异常」。当函数中存在抛出检查型异常的操作时,调用该函数的函数也必须对该异常进行处理,如不进行处理则必须在调用函数上声明throws语句。
  • 另一类是非检查异常,在Java中所有 RuntimeException类的派生类都是非检查型异常(运行时异常)。检查型异常是JAVA首创的,在编译期对异常的处理有强制性的要求。在JDK代码中大量的异常属于检查型异常,包括IOException,SQLException等等。与检查型异常对比,非检查型异常可以不在函数声明中添加throws语句,调用函数上也不需要强制处理。

常见的检查异常:

5982616-ad31cf5b8e2cbb36.png

常见的非检查异常:

webp

三. 捕获异常

try
{//程序代码(也是保护代码)
}catch(ExceptionName  e){
//catch块
}

如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
例子:

import java.io.FileNotFoundException;
public class ExceptionTest {
    public static void main(String[] args)
    {
        ExceptionTest1();
    }
    //try-catch捕获异常
    public static void ExceptionTest1()
    {
        try {
            int[] a = {1, 2};
            int b = a[10];
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            System.out.println("错误类型是:"+e);
        }
    }
  }
  程序执行输出结果是:
  错误类型是:java.lang.ArrayIndexOutOfBoundsException: 10
  Process finished with exit code 0

1. 多重捕获

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}

可以在 try 语句后面添加任意数量的 catch 块。如果保护代码中发生异常,异常被抛给第一个 catch 块。如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。如果不匹配,它会被传递给第二个 catch 块。如此,直到异常被捕获或者通过所有的 catch 块。

class MyMath{
    public static int div(int x,int y) throws Exception{
        return x/y;
    }
}
public class Main {
    public static void main(String args[]) throws Exception{
        System.out.println(MyMath.div(10,0));
    }
}

 如果主方法继续向上抛出异常,那么就表示此异常将交由JVM负责处理。


2. finally关键字

finally 关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally 代码块中的代码总会被执行。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。finally 代码块出现在 catch 代码块最后,语法如下:

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码
}

例如:

import java.io.FileNotFoundException;

public class ExceptionTest {
    public static void main(String[] args)
    {
        ExceptionTest2();
    }
    //try-catch捕获异常
    //finally
    public static void ExceptionTest2()
    {
        int[] data={1,2};
        try {
            System.out.println(data[10]);
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            System.out.println("错误信息是:"+e);
        }
        finally {
            System.out.print("执行finally语句部分:");
            data[0]=11;
            System.out.print("data数组0位置存储的数据是:"+data[0]);
        }

    }
}
程序输出结果是:
错误信息是:java.lang.ArrayIndexOutOfBoundsException: 10
执行finally语句部分:data数组0位置存储的数据是:11
Process finished with exit code 0

注意下面事项:
catch 不能独立于 try 存在。
在 try/catch 后面添加 finally 块并非强制性要求的。
try 代码后不能既没 catch 块也没 finally 块。
try, catch, finally 块之间不能添加任何代码。

四. 声明自定义异常

在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
所有异常都必须是 Throwable 的子类。
如果希望写一个检查性异常类,则需要继承 Exception 类。
如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
可以像下面这样定义自己的异常类:

class MyException extends Exception{
}

五. throws/throw 关键字

如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。

1. throws关键字

通过之前的程序可以发现,在执行程序的过程中可能会产生异常,但是如果说现在假设你定义了一个方法,实际上就应该明确地告诉使用者,这个方法可能会产生何种异常,那么此时就可以在方法的声明上使用throws关键字。

例子:

class MyMath{
    public static int div(int x,int y) throws Exception{
        return x/y;
    }
}
public class Main{
    public static void main(String args[]) throws Exception{
        System.out.println(MyMath.div(10,0));
    }
}

在主方法上继续抛出异常主方法本身也是一个方法,那么实际上主方法也可以继续向上抛出。

 

class MyMath{
    public static int div(int x,int y) throws Exception{
        return x/y;
    }
}
public class Main{
    public static void main(String args[]) throws Exception{
        System.out.println(MyMath.div(10,0));
    }
}

如果主方法继续向上抛出异常,那么就表示此异常将交由JVM负责处理。

2. throw关键字

throw关键字,此关键字的主要作用在于表示手工进行异常的抛出,即:此时将手工产生一个异常类的实例化对象,并且进行异常的抛出处理。

public class Main002 {
    public static void main(String[] args) {
        try {//异常对象不是由系统生成的,而是由手工定义的
            throw new Exception("自己抛出一个异常");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  • throw:在代码块中使用的,主要是手工进行异常对象的抛出。
  • throws:在方法定义上使用的,表示此方法中可能产生的异常明确告诉调用处,由调用处进行处理。

六、try-catch-finally实例

返回值原理:返回值在try中被缓存了,后面的更改并不能修改到缓存了的返回值。

先记录原理,后续写实例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值