Java 异常

1、Throwable 类

Java 异常层次结构:

在这里插入图片描述

异常分类:

  • 检查型异常:除非检查型异常以外的所有异常
  • 非检查型异常:派生于Error类或RuntimeException类的所有异常

一个方法必须声明或捕获所有可能抛出的检查型异常,而非检查型异常要么在你的控制之外(Error),要么从一开始就应该避免(RuntimeException)。

2、抛出异常

抛出EOFException异常:

throw new EOFException();

3、处理异常

2.1 声明异常

在方法的首部声明这个方法可能抛出一个异常:

public FileInputStream(String name) throws FileNotFoundException

如果一个方法可能抛出多个检查型异常,那么需要在方法的首部列出所有的异常类:

public Image loadImage(String s) throws FileNotFoundException, EOFException

不应该声明从ErrorRuntimeException继承的非检查型异常。

2.2 捕获异常

① try/catch/finally 语句

下面是关闭输入流的代码示例:

InputStream in = ...;
try {
    try {
        code that might throw exceptions
    }
    finally {
        in.close();
    }
} catch(IOException e) {
    show error message
}

使用规则:

  • 一个 catch 可以捕获多个异常,不过需要注意此时异常变量隐含为final变量,例如在以下子句体中不能为 e 赋其他值:catch (FileNotFoundException | UnknownHostException e) {…}
  • 可以在 catch 中将捕获的异常抛出,或者抛出一个新的异常,并使用initCause方法将原始异常设置为新异常的“原因”,当捕获到这个新异常时,我们可以使用getCause方法获取原始异常
  • 不管是否有异常被捕获,finally 子句中的代码都会执行(在方法返回之前执行)
  • finally 用于清理资源,不要把改变控制流的语句(return,throw,break,continue)放在 finally 子句中

下面演示在 finally 中使用return存在的问题:

public class Main {
    public static String foo() {
        try {
            return "try!!!";
        } finally {
            return "finally!!!";
        }
    }

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

打印结果为finally!!!,即 finally 中的 return 将会先于 try 中的 return 执行!!!

② try-with-resources 语句

在 Java 7 中,如果资源实现了AutoCloseable接口,我们可以使用try-with-resources语句处理资源:

try (Resource res = ...) {
    work with res
}

try 块退出时,会自动的调用资源的close方法,关闭资源。(close 是 AutoCloseable 接口中的方法)

使用规则:

  • try-with-resources 语句可以有 catch 和 finally 子句,这些子句在关闭资源之后执行
  • 在 Java 9 中,可以在 try 首部中提供之前声明的finaleffective final变量
  • 如果 try 和 close 都抛出异常,则 close 方法抛出的异常会被抑制,并由addSuppressed方法增加到try中的异常,如果想查看被抑制的异常,我们可以使用getSuppressed方法获取被抑制的异常数组

我们对最后一点进行演示:

class Demo extends InputStream {
    @Override
    public int read() throws IOException {
        return 0;
    }

    @Override
    public void close() throws IOException {
        super.close();
        throw new IOException();
    }
}

public class Main {
    public static void foo() {
        try(Demo demo = new Demo()) {
            throw new EOFException();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(Arrays.toString(e.getSuppressed()));
        }
    }

    public static void main(String[] args) {
        foo();
    }
}

输出结果:

在这里插入图片描述

③ 异常丢失

Java 的异常实现存在异常丢失的问题,如下所示:

public class Main {
    public static void foo() {
        try {
            throw new IOException();
        } finally {
            return;
        }
    }

    public static void main(String[] args) {
        foo();
    }
}

运行上述代码,我们会发现:在 try 中抛出了异常,它却没有产生任何输出。

这就是异常丢失,如果我们在 finally 中也使用 throw 抛出一个异常,结果只会输出新抛出的异常,try 中的异常同样会丢失。

2.3 如何选择处理方式

一般经验是,要捕获那些你知道如何处理的异常,而继续传播那些你不知道怎样处理的异常。

4、创建异常类

当遇到标准的异常类无法描述清楚问题时,我们可以创建自己的异常类。自定义的异常类需要派生于 Exception 类或其子类,并且应该包含一个默认构造器和一个包含详细描述信息的构造器。

class FileFormatException extends IOException {
    public FileFormatException() {}
    public FileFormatException(String gripe) {
        super(gripe);
    }
}

如有错误,欢迎指正。.... .- ...- . .- -. .. -.-. . -.. .- -.-- -.-.--

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值