Java基础Java学习笔记今日看点

Java编码中异常的使用建议

2016-11-16  本文已影响476人  typeorigin
source_code.jpg

异常,精确计算机世界里的不安定份子。当然说的是异常的使用,似乎没有什么统一的标准。但是我觉得在一个团队或者是系统里面还是应该遵循一定的规矩。

无规矩不方圆。

下面列一下目前工作中总结的一些使用经验

首先看下Java异常的分类。

Java 异常的分类

异常机制提供了一种异常事件的冒泡处理机制,你可以选择你想处理这个异常的层次。 如果没有异常的话,你就要在很低的层次处理异常,并想办法通知上层

异常使用中的困惑

在我的使用或者团队大家的共识是,异常使用困惑的地方主要集中在下面两点:

所以接下来主要围绕着两个困惑来进行解答

先来看看受检和非受检异常使用的时机,此处非受检指的是 RuntimeException

受检异常的使用时机

Use checked exceptions for conditions from which the caller
can reasonably be expected to recover

当你面临上面的情景时可以采用受检异常

非受检异常的使用时机

Use runtime exceptions to indicate programming errors (Bugs) - From Effective Java

RuntimeException 通常指程序运行时的错误,可以引申为调用方错误的使用了API或者类库设计者的问题。

Runtime exceptions can occur anywhere in a program, and in a typical one they can be very numerous. Having to add runtime exceptions in every method declaration would reduce a program's clarity. Thus, the compiler does not require that you catch or specify runtime exceptions - From Oracle The Java™ Tutorials

上面说到RuntimeException是程序中非常常见的错误,因此没有强制让编译器来检查这一类错误。但是程序员自己就需要做好预先检查的工作。RuntimeException 有个好处就是能够穿透到最上层,让最上层做决定。因此可以围绕下面几点来使用RuntimeException

错误码和异常使用的时机

在没有异常机制的程序语言中,可能比较依赖错误码等来作为业务层面的流程判断。但是在Java中提供了异常的处理机制,这种冒泡处理机制,让你可以选择你想处理这个异常的层次。 如果没有异常的话,你就要在很低的层次处理异常,并想办法通知上层。

总结来讲,错误码和异常的特点就是

作为Java程序员,应该优先使用异常来反馈程序中的异常情况。

使用异常来区分正常的业务场景和错误的业务路径

    public String foo() IOException, FileNotFoundException {
        ...
    }

    // 一个好的使用方法应该是这样
    try {
        foo();
    } catch (IOException ioe) {
        // 给出友好的提示信息
    } catch (FileNotFoundException fe) {
        // 给出友好的提示信息        
    }

一种异常和错误码的混合方案

定义一个业务异常,然后异常中添加字段来表示错误码。

enum ErrorCode {
    INVALID_PARAM, INVALID_PATH, INVALID_STAUS;
}

class MyException extend Exception {
    public MyException(String msg) {
        super(msg);
    }
}

// 使用场景
public String foo() throws MyException {
    if (...) {
        throw new MyException(ErrorCode.INVALID_PARAM.getName());
    }

    ...

    if (...) {
        throw new MyException(ErroCode.INVALID_PATH.getName());
    }

    ...

    if (...) {
        throw new MyException(ErrorCode.INVALID_STATUS));
    }
}


错误码和异常使用的建议

最后是异常使用的一些实践

异常处理的实践

具体来讲就是

try-catch-finally 释放资源

OutputStreamWriter out = ... 
java.sql.Connection conn = ... 
try { 
    ...
} catch(SQLException sqlex) { 
    ...
} catch(IOException ioex) { 
    ...
} finally { 
    if (conn != null) { 
        try { 
            conn.close(); 
        } catch(SQLException sqlex2) { 
            ...
        } 
    } 

    if (out != null) { 
        try { 
            out.close(); 
        } catch(IOException ioex2) { 
        ...
        } 
    } 
}

不要将异常用作控制流(if-else)

虽然异常本身具有流程控制的属性,但是直接作为类似 if-else这样的方式来使用还是不应该的

public void check(String filePath) FileNotFoundException, FileExistException  {
    ...
} 

// 使用
try {
    check();
} catch (FileNotFoundException fne) {
    // do-file not found things ..
} catch (FileExistException fee) {
    // do-file found things
}

不要忽略异常

try {
    Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException ex) {} //忽略的异常,这样要不得。出了问题坑自己、坑队友
    
// 接收异常
try {
    ...
} catch (Exception e) {  // 过分泛华的异常,不利于排查问题
    ...
}

// 抛出异常
try {
    ...
} catch (IOException ioe) {
    throw new Exception(ioe); // 泛化了异常, 外层调用丢失了异常类型的优势
}

// 自定义异常
try {
    ...
} catch (SqlException sqle) {
    throw new MyOwnException(); // 定义了新的异常,但是丢了原始异常信息
}

生产代码不要 printStackTrace();

// 不好的方式
try {
    ... 
} catch (IOException e) {
    e.printStackTrace();
}

try {
    ...
} catch (IOException e) {
    logger.error("message here" + e);
}

try {

} catch (IOException e) {
    logger.error("message here" + e.getMessage());
}

// 比较好的方式
try {
    ...
} catch (IOException e) {
    logger.error("message here", e);
}

异常的捕获范围

// bad case
try {
    while(rs.hasNext()) {
        foo(rs.next());
    }
} catch (SomeException se) {
    ...
}

// good case
while(rs.hasNext()) {
    try {
        foo(rs.next());
    } catch (SomeException se) {
        ...
    }
} 

参考资料

http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html

http://stackoverflow.com/questions/6115896/java-checked-vs-unchecked-exception-explanation

http://www.javapractices.com/topic/TopicAction.do?Id=129

http://www.ibm.com/developerworks/cn/java/j-lo-exception/index.html

http://www.blogjava.net/freeman1984/archive/2013/07/26/148850.html

上一篇下一篇

猜你喜欢

热点阅读