(事先声明:该文章并非完全是我自己的产出,更多的是我个人在看到资料后通过理解并记录下来,作为自己阅读后的一个笔记;我现在试图对自己多年工作中的知识点做一个回顾,希望能融会贯通)

(此文参考<Java核心技术36讲>第二讲)

 

Exception & Error

Java的Exception和Error都继承了Throwable,且仅有Throwable类能被抛出(throw)和捕获(catch)。

Error是指正常情况下不会发现的,并且发现后无法恢复;此类错误不需要捕获,如:OutOfMemoryError,StackOverflowError,正常代码中无法对此类错误进行捕获。

Exception一搬是指程序运行是出现的意外情况 - 该事件发生是在意料之中的,且有可能恢复;可以进行捕获并相应处理。如: NumberFormatException, ValidateException(自定义).  异常又分为可检查(checked)和不检查(un-checked)。

1. Checked:在编译时会强制要求进行捕获,如在方法中有定义抛出的异常,则调用该方法时需要捕获该异常并进行处理。



public void methodA() throws ValidateException {
        // do thing
        throw new ValidateException("Number exception");
    }

    public void handleException() {
        ExceptionHandling eh = new ExceptionHandling();
        eh.methodA();  // <--- need catch the exception here
    }



 

2. Un-checked:  运行时出现的异常,如在处理对象时发现对象为空(NullPointException),或者ClassCastException,此类异常通常不会在编译时要求显式处理。而是根据代码实现者的具体实现来捕获。

 

Exception处理 - try-with-resources

基本的语法有 try-catch-finally, throw new xxxException("Exception message"),  throws xxxException (方法定义).

Java7之后,引入了try-with-resources: 当一个外部资源实现了Autocloseable / Closeable接口时,可以将原来复杂的try-catch-finally-try-catch替换成自动关闭。

旧的实现:



public void readFile(String fileName) {
    FileInputStream is = null;
    try {
        is = new FileInputStream(new File(fileName));
        log.info("File content:\n {}", is.read()); 
    }  catch(IOException e) {
        throw new RuntimeException(e.getMessage, e);
    } finally {
        if(is != null) {
            try {
                is.close();
            } catch (IOException e1) {
                throw new RuntimeException(e1.getMessage, e1);
            }
        }
    }
}



新实现:

public void readFile(String fileName) {
    try (FileInputStream is = new FileinputStream(new File(fileName))) {
        log.info("File content:\n {}", is.read());
    } catch (IOException e) {
        throw new RuntimeException(e.getmessage, e);
    }
}

 

Exception处理 - Multiple exception


try {
    // do sth
} catch (IOException | ValidateException) {
    // handle exception here
}


 

日常使用建议

在日常编写代码过程中,处理异常应该尽量遵循一些好的经验。

尽可能捕获具体的异常,而不通用异常: 如Catch(NumberFormatException e), 而不是Catch(Exception e)

不要吞掉异常(Swallow Exception),应该输出有用的信息。

尽早抛出异常,比如在正常代码里,如果一行代码包含多个对象且出现NPE时, 很难判断是哪个对象为空,因此可以在有可能出现对象为空且该对应一定不能为空时增加测试条件:

Preconditions.checkNotNull(neme, "neme can't be null");