阿里Java开发手册思考(五)

作者: 史培培 | 来源:发表于2017-12-17 21:35 被阅读0次
    题图:by pixel2013 From pixabay

    上期我们分享了Java中日志的处理(下):Java中日志实际使用中的相关注意点

    本期我们将分享Java中异常的处理

    异常定义

    在《java编程思想》中这样定义异常:阻止当前方法或作用域继续执行的问题。

    异常分类

    首先我们看下Java中异常的继承关系:

    可以看出,Throwable有两个子类:ErrorException

    • Error
      • VirtualMachineError,典型的有StackOverFlowOutOfMemory
      • AWTError
    • Exception
      • IOException
      • ...
      • RuntimeException

    Exception分为CheckedException和UncheckedException,那么CheckedException和UncheckedException区别是什么呢?

    • UncheckedException:派生于Error或者RuntimeException的异常
    • CheckedException:所有其他的异常

    异常处理机制

    异常处理机制分为:抛出异常和捕捉异常

    抛出异常:方法上使用throws,方法内使用throw
    捕捉异常:使用try-catch或者try-catch-finally

    原则,正如手册上所说:

    • 不要直接忽略异常
    • 不要用try-catch包住太多语句
    • 不要用异常处理来处理程序的正常控制流
    • 不要随便将异常迎函数栈向上传递,能处理尽量处理

    何时向上传播?

    • 当你认为本异常应该由上层处理时,才向上传播

    注意点

    • finally语句块一定会执行吗?

    不一定会,以下两种情况finally语句块不会执行

    1. 未执行到try语句块
    2. try语句块中有System.exit(0);
    • finally语句块的执行顺序

    首先看没有控制语句的情况:

    public static void main(String[] args) {
        try {
            System.out.println("try block");
        } finally {
            System.out.println("finally block");
        }
    }
    

    输出没有疑问:
    try block
    finally block

    1、如果try中有控制语句(returnbreakcontinue),那finally语句块是在控制转义语句之前执行还是之后执行?

    private static String test1() {
        System.out.println("test1()");
        return "return";
    }
    
    private static String test() {
        try {
            System.out.println("try block");
            return test1();
        } finally {
            System.out.println("finally block");
        }
    }
    
    public static void main(String[] args) {
        System.out.println(test());
    }
    

    输出:
    try block
    test1()
    finally block
    return

    所以说,如果try中有控制语句(returnbreakcontinue),那finally语句块是在控制转义语句之前执行

    2、如果catch语句中有控制语句(returnbreakcontinue),那finally语句块是在控制转义语句之前执行还是之后执行?

    private static String test1() {
        System.out.println("test1()");
        return "return";
    }
    
    private static String test() {
        try {
            System.out.println("try block");
            System.out.println(1 / 0);
            return test1();
        } catch (Exception e) {
            System.out.println("catch block");
            return test1();
        } finally {
            System.out.println("finally block");
        }
    }
    
    public static void main(String[] args) {
        System.out.println(test());
    }
    

    输出:
    try block
    catch block
    test1()
    finally block
    return

    所以说,如果catch语句中有控制语句(returnbreakcontinue),那finally语句块是在控制转义语句之前执行

    • finally里的变量
    public static int test() {
        int i = 0;
        try {
            return i;
        } finally {
            i++;
        }
    }
    
    public static void main(String[] args) {
        System.out.println(test());
    }
    

    输出:
    0

    咦?很奇怪,为什么是0,而不是1呢?

    通过反编译生成的class,我们就能知道原因了

    int i = 0;
    try {
        return i;
    } finally {
        int iTemp = i++;
    }
    

    原来,i++后只是赋值给了一个新的局部变量,i本身并没有变,这一点和函数的形参一样,如果传的是引用类型的,那么值会变,如果传的不是引用类型,那么值是不会改变的,改变的也只是局部变量。

    相关文章

      网友评论

        本文标题:阿里Java开发手册思考(五)

        本文链接:https://www.haomeiwen.com/subject/scbuwxtx.html