sentencias programacion practicas funciones estandares estandar código convenciones codigos codigo codificacion buenas java compiler-construction dead-code constant-expression code-elimination

programacion - funciones estandar en java



Expresiones constantes Java y eliminación de código (2)

Como es parte de la "firma" pública de la clase referenciada, se supone que es constante. Básicamente, la idea es que final significa final, y si lo cambias, es tu culpa.

Esto es similar a las firmas de métodos reales de las clases referenciadas, también tomadas como están en el momento de la compilación. Por eso, si compila el código con una versión de una biblioteca y la ejecuta contra otra, puede obtener NoSuchMethodError .

Actualización: en realidad, el JLS ofrece una garantía aún más sólida :

Si un campo es una variable constante (§4.12.4), eliminar la palabra clave final o cambiar su valor no romperá la compatibilidad con los archivos binarios preexistentes haciendo que no se ejecuten, pero no verán ningún valor nuevo para el uso. del campo a menos que sean recompilados. Esto es cierto incluso si el uso en sí no es una expresión constante en tiempo de compilación (§15.28).

Este resultado es un efecto secundario de la decisión de apoyar la compilación condicional, como se discutió al final de §14.21.

Como se discutió aquí , javac y otros compiladores de Java pueden proporcionar capacidades de eliminación de código para declaraciones-y- if donde la condición es una "Expresión constante" .

¿Cómo se ve afectado si mi código usa una expresión constante que depende de otras expresiones constantes definidas en paquetes diferentes?

Por ejemplo, digamos que tengo las siguientes clases en los respectivos paquetes especificados:

package foo; public class Foo { public static final boolean CONDITION = false; }

y

package bar; import foo.Foo; public class Bar { public void test() { if (Foo.CONDITION) { System.out.println("This line of code could be eliminated."); } else { System.out.println("This line of code will be executed."); } } }

Claramente, si el paquete foo se carga en tiempo de ejecución desde un archivo jar externo, el compilador no puede suponer técnicamente que Foo.CONDITION será falso y no debería eliminar el true -branco de la declaración -si.

Considerando que, si Foo y Bar estuvieran realmente en el mismo paquete, la rama true definitivamente debería eliminarse (si el compilador admite la eliminación del código).

No estoy muy seguro de cómo expresar mejor esta pregunta, pero: ¿Qué tan "cercano" necesita Foo para Bar para que una expresión constante en Foo también se considere constante en Bar ? ¿Tendrían que estar en el mismo archivo? el mismo paquete? el mismo archivo jar? o no tiene importancia Foo.CONDITION (es decir, ¿el compilador siempre consideraría Foo.CONDITION como constante y usaría el valor encontrado en la ruta de compilación durante el tiempo de compilación)?


No importa qué tan cerca esté tu constante. Si es una constante de tiempo de compilación como se define en la especificación , estará en línea. Las finales estáticas (constantes) están inline por especificación de Java (aunque tampoco encontré la especificación). Este artículo sobre el mundo de Java discute el tema con cierto detalle. Lo relevante:

De acuerdo con la Especificación del lenguaje Java, cualquier campo final estático inicializado con una expresión que pueda evaluarse en tiempo de compilación debe compilarse a un código de bytes que "incorpore" el valor del campo. Es decir, ningún enlace dinámico estará presente dentro de la clase principal, diciéndole que obtenga el valor de A de InterfaceA en tiempo de ejecución. En cambio, el literal 1 se compilará en Main.main () directamente.