0
点赞
收藏
分享

微信扫一扫

[Java]浅谈Java的异常体系

兽怪海北 2021-09-28 阅读 57

为什么需要异常

理想的情况下,程序是不会有BUG的。但是现实的情况是:处处都可能引发BUG,比如一个糟糕的输入、需要访问的资源不存在、网络出现抖动、服务器资源不足等等。这就要求我们的程序需要一个机制来解决以下问题:

  1. 报告当前的错误信息
  2. 中断,发生了错误的逻辑不向下执行代码
  3. 抛出一个信号,让程序对此做出判断进行进一步的处理。

Java设计了一个异常处理的错误捕获机制来解决这些问题。

异常层次结构

可以看到,所有的异常都是由Throwable继承而来,而在下一层分为了2个分支:ErrorException

  • Error
  • Exception
    1. RuntimeException-由于程序错误导致的异常
    1. 非RuntimeException-程序没有问题,因为外界资源引起的异常。(IOException)

可见,RuntimeException通常是可以通过程序员的编程能力去解决的。而对于非RuntimeException,这是不可预期的,因为谁会指定这个一个该存在的文件是否被人为地删除了呢,因此这是根据资源环境决定的.

unchecked异常与checked异常

Java语言规范将派生与Error类或者RuntimeException类的所有异常称为非检查异常,所有其他的异常称为受查异常。这是什么意思呢?也就是Java认为,OOM和RumtimeException这种都是程序运行起来才会出现的,这些应该由程序员本身去规避。而由于环境的不确定因素引发的异常,比如说IO异常,那么就需要主动去解决,你可以选择throw,或者try catch,但是你不能不处理,否则无法通过编译。

如何处理异常

  • check异常可以通过throws声明
public class ThrowsException {
/**
* 我们声明了一个不存在的文件,试图获取它的输出流,这时IDE会提示我们需要处理受检查的异常
* @param args
* @throws FileNotFoundException
*/

public static void main(String[] args) throws FileNotFoundException {
File noExitsFile = new File("D:\\logs\\notExistFile");
FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);
}
}
  • 使用try catch关键字处理异常
    public static void main(String[] args){
File noExitsFile = new File("D:\\logs\\notExistFile");
try {
FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);
} catch (FileNotFoundException e) {
// 实际工作中,应使用自定义异常将此错误抛出
e.printStackTrace();
}
}
    public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(noExitsFile);
} catch (FileNotFoundException e) {
// 实际工作中,应使用自定义异常将此错误抛出
e.printStackTrace();
} finally {
if (Objects.nonNull(fileOutputStream)) {
try {
fileOutputStream.close();
} catch (IOException e) {
Logger.getGlobal().info("An exception occurred when closing the stream");
}
}
}
}

使用try-with-resource来控制你的资源

 try(Resource resource = new Resource()){
// do Something
}catch(IOException e){
// handle Exception
}

案例:

    public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");
try (FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile)) {
FileDescriptor fd = fileOutputStream.getFD();
} catch (IOException e) {
// 实际工作中,应使用自定义异常将此错误抛出
e.printStackTrace();
}
}

多个资源如何声明:

    public static void main(String[] args) {

File noExitsFile = new File("D:\\logs\\notExistFile");
try (FileOutputStream fileOutputStream = new FileOutputStream(noExitsFile);
FileInputStream fileInputStream = new FileInputStream(noExitsFile);) {
FileDescriptor fd = fileOutputStream.getFD();
FileDescriptor fd1 = fileInputStream.getFD();
} catch (IOException e) {
// 实际工作中,应使用自定义异常将此错误抛出
e.printStackTrace();
}
}

处理异常的一些原则

  • 不要使用try catch嵌套这种方式进行编程,应将可能发生异常的代码块用一个try catch包住,然后对不同的异常进行catch
  • 尽量抛出职责足够小的异常类,不要直接抛出IOException或者RuntimeException这种通用性较强的类,这样容易定位问题
  • try catch住的异常必须处理,不要吞掉异常
  • 使用throws可以让代码更加简洁,并且交由特定的异常处理类进行处理
  • 使用Spring的声明式事务注解时,应注意只对RuntimeException进行处理,最好手动声明rollback
  • 涉及资源使用的类需要声明finally对资源进行回收,或者使用Java7的try-with-resource
举报

相关推荐

0 条评论