¿Por qué el comstackdor de Java no entiende que esta variable siempre se inicializa?

class Foo{ public static void main(String args[]){ final int x=101; int y; if(x>100){ y=-1; } System.out.println(y); } } 

El comstackdor de Java entiende que la condición de la statement if es siempre cierta y, por lo tanto, y siempre se inicializará. No hay error de comstackción, como se esperaba.

 class Bar{ public static void main(String args[]){ final int x; x=101; int y; if(x>100){ y=-1; } System.out.println(y); } } 

Pero cuando rompo la statement y la inicialización de x en dos líneas, el comstackdor no parece entender que la condición siempre es verdadera y que siempre se inicializará.

 final int x; x=101; byte b; b=x; System.out.println(b); 

Lo mismo sucede aquí y el comstackdor da una pérdida de error de precisión.

 final int x=101; byte b; b=x; System.out.println(b); 

De nuevo, el comstackdor puede entender que x está dentro del rango de b.

Tiene que ver con cómo el comstackdor determina si una statement se ejecutará o no. Está definido en el JLS # 16 :

Cada variable local y cada campo final en blanco debe tener un valor definitivamente asignado cuando se produce cualquier acceso de su valor.

En su caso, el comstackdor no puede determinar que y ha sido definitivamente asignado y le da un error. Esto se debe a que necesitaría determinar que la condición siempre es verdadera y que solo es posible si la condición en if es una expresión constante .

JLS # 15.28 define expresiones constantes :

Una expresión constante de tiempo de comstackción es una expresión que denota un valor de tipo primitivo o una cadena que no se completa abruptamente y se compone solo con lo siguiente:

  • […]
  • Nombres simples (§6.5.6.1) que se refieren a variables constantes (§4.12.4).

El JLS # 4.12.4 define variables de constantes como:

Una variable de tipo primitivo o tipo String, que es definitiva e inicializada con una expresión constante en tiempo de comstackción, se denomina variable constante.

En su caso, final int x = 101; es una variable constante pero final int x; x = 101; final int x; x = 101; no es.

Como parte del objective de la portabilidad, existe un conjunto muy específico de reglas para lo que un comstackdor debería aceptar y lo que debería rechazar. Esas reglas permiten y requieren solo una forma limitada de análisis de flujo al determinar si una variable se asigna definitivamente en su uso.

Consulte la especificación del lenguaje Java Capítulo 16. Asignación definida

La regla crítica es la de 16.2.7. if Declaraciones , caso “if (e) S”. La regla para ser definitivamente asignada se expande a:

V se asigna después de if (e) S si, y solo si, se asigna V después de que S y V se asignan después de e cuando es falso.

y es la V relevante. No está asignado antes de la instrucción if. De hecho, se asigna después de S , y = {y = -1;} pero no hay nada que lo asigne cuando x> 100 es falso.

Por lo tanto, y no se asigna definitivamente después de la instrucción if.

Un análisis de flujo más completo determinaría que la condición x> 100 siempre es cierta, pero el JLS requiere que el comstackdor rechace el progtwig en función de estas reglas específicas.

La variable final está bien. La regla es en realidad:

“Es un error en tiempo de comstackción si se asigna una variable final a menos que definitivamente no esté asignada (§16) inmediatamente antes de la asignación”.

La statement lo deja definitivamente sin asignar, e incluso el análisis de flujo limitado puede determinar que x todavía no está asignado en la asignación.

Lo que has hecho para la variable x en el segundo código se llama variable final en blanco . Si una variable final no se inicializa cuando se declara, entonces se conoce como una variable final en blanco.

Muchos desarrolladores de Java piensan que el valor de una variable final se conoce en el tiempo de comstackción. Esto NO siempre es verdad. Se dice que el valor de una variable final en blanco NO se conoce en el momento de la comstackción. Por lo tanto, su segundo código le dará un error de comstackción. El comstackdor puede ver que ha inicializado la variable final x , pero comstackr no sabe su valor. Entonces el comstackdor no puede resolver la statement if. Por lo tanto, cree que la variable y no está inicializada.

Puede leer más acerca de las variables finales de Java aquí .

Intereting Posts