坑2:finally中的代码“不执行”
如果说上面的示例比较简单,那么下面这个示例会给你不同的感受,直接来看代码。
① 反例代码
public static void main(String[] args) throws FileNotFoundException { System.out.println("执行结果:" + getValue()); } private static int getValue() { int num = 1; try { return num; } finally { num++; } }
以上代码的执行结果如下:
② 原因分析
本以为执行的结果会是 2,但万万没想到竟然是 1,用马大师的话来讲:「我大意了啊,没有闪」。
有人可能会问:如果把代码换成 ++num,那么结果会不会是 2 呢?
很抱歉的告诉你,并不会,执行的结果依然是 1。那为什么会这样呢?想要真正的搞懂它,我们就得从这段代码的字节码说起了。
以上代码最终生成的字节码如下:
// class version 52.0 (52) // access flags 0x21 public class com/example/basic/FinallyExample { // compiled from: FinallyExample.java // access flags 0x1 public <init>()V L0 LINENUMBER 5 L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this Lcom/example/basic/FinallyExample; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x9 public static main([Ljava/lang/String;)V throws java/io/FileNotFoundException L0 LINENUMBER 13 L0 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; NEW java/lang/StringBuilder DUP INVOKESPECIAL java/lang/StringBuilder.<init> ()V LDC "\u6267\u884c\u7ed3\u679c:" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKESTATIC com/example/basic/FinallyExample.getValue ()I INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L1 LINENUMBER 14 L1 RETURN L2 LOCALVARIABLE args [Ljava/lang/String; L0 L2 0 MAXSTACK = 3 MAXLOCALS = 1 // access flags 0xA private static getValue()I TRYCATCHBLOCK L0 L1 L2 null L3 LINENUMBER 18 L3 ICONST_1 ISTORE 0 L0 LINENUMBER 20 L0 ILOAD 0 ISTORE 1 L1 LINENUMBER 22 L1 IINC 0 1 L4 LINENUMBER 20 L4 ILOAD 1 IRETURN L2 LINENUMBER 22 L2 FRAME FULL [I] [java/lang/Throwable] ASTORE 2 IINC 0 1 L5 LINENUMBER 23 L5 ALOAD 2 ATHROW L6 LOCALVARIABLE num I L0 L6 0 MAXSTACK = 1 MAXLOCALS = 3 }