Declarar una variable finalo no declararla final, pero mantenerla efectivamente final puede resultar (depende del compilador) en un código de bytes diferente.
Echemos un vistazo a un pequeño ejemplo:
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
}
}
El maincódigo de bytes correspondiente del método (Java 8u161 en 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 tabla de números de línea correspondiente:
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
Como vemos el código fuente en líneas 12, 13, 14no aparece en el código de bytes. Eso es porque ies truey no cambiará su estado. Por lo tanto, este código es inalcanzable (más en esta respuesta ). Por la misma razón, el código en la línea 9también falla. El estado de ino tiene que ser evaluado, ya que es trueseguro.
Por otro lado, aunque la variable jes efectivamente final , no se procesa de la misma manera. No hay tales optimizaciones aplicadas. El estado de jse evalúa dos veces. El código de bytes es el mismo independientemente de que jsea efectivamente final .