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

阿里Java开发手册思考(五)_第1张图片
题图: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开发手册思考(五))