Difference between final and effectively final

后端 未结 14 2993
孤独总比滥情好
孤独总比滥情好 2020-11-22 00:38

I\'m playing with lambdas in Java 8 and I came across warning local variables referenced from a lambda expression must be final or effectively final. I know tha

14条回答
  •  醉梦人生
    2020-11-22 00:47

    Declaring a variable final or not declaring it final, but keeping it effectively final may result (depends on compiler) in different bytecode.

    Let's have a look on a small example:

        public static void main(String[] args) {
            final boolean i = true;   // 6  // final by declaration
            boolean j = true;         // 7  // effectively final
    
            if (i) {                  // 9
                System.out.println(i);// 10
            }
            if (!i) {                 // 12
                System.out.println(i);// 13
            }
            if (j) {                  // 15
                System.out.println(j);// 16
            }
            if (!j) {                 // 18
                System.out.println(j);// 19
            }
        }
    

    The corresponding bytecode of the main method (Java 8u161 on Windows 64 Bit):

      public static void main(java.lang.String[]);
        Code:
           0: iconst_1
           1: istore_1
           2: iconst_1
           3: istore_2
           4: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
           7: iconst_1
           8: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
          11: iload_2
          12: ifeq          22
          15: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
          18: iload_2
          19: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
          22: iload_2
          23: ifne          33
          26: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
          29: iload_2
          30: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
          33: return
    

    The corresponding line number table:

     LineNumberTable:
       line 6: 0
       line 7: 2
       line 10: 4
       line 15: 11
       line 16: 15
       line 18: 22
       line 19: 26
       line 21: 33
    

    As we see the source code at lines 12, 13, 14 doesn't appear in the byte code. That's because i is true and will not change it's state. Thus this code is unreachable (more in this answer). For the same reason the code at line 9 misses too. The state of i doesn't have to be evaluated since it is true for sure.

    On the other hand though the variable j is effectively final it's not processed in the same way. There are no such optimizations applied. The state of j is evaluated two times. The bytecode is the same regardless of j being effectively final.

提交回复
热议问题