Déclarer une variable finalou ne pas la déclarer final, mais la garder effectivement finale peut entraîner (dépend du compilateur) un bytecode différent.
Jetons un coup d'œil sur un petit exemple:
    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
        }
    }
Le bytecode correspondant de la mainméthode (Java 8u161 sur 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
La table des numéros de ligne correspondante:
 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
Comme on le voit le code source au niveau des lignes 12, 13, 14ne figure pas dans le code d'octets. C'est parce que ic'est trueet ne changera pas son état. Ainsi, ce code est inaccessible (plus dans cette réponse ). Pour la même raison, le code à la ligne 9manque également. Il in'est pas nécessaire d'évaluer l'état de car il est truecertain.
D'un autre côté, bien que la variable jsoit effectivement finale, elle n'est pas traitée de la même manière. Il n'y a pas de telles optimisations appliquées. L'état de jest évalué deux fois. Le bytecode est le même, même s'il jest effectivement définitif .