estaticas - variable final estática pública en una clase java importada
variable static java (5)
Me encuentro con un código Java en mi lugar de trabajo. Aquí está el escenario: hay 2 clases: ClassA
y ClassB
.
ClassA
no tiene nada excepto 4 valores de cadena final públicos estáticos dentro de él. Su propósito es usar esos valores como ClassA.variable
(no me preguntes por qué, no es mi código).
ClassB
importa ClassA
. Edité los valores de cadena en ClassA
y lo compilé. Cuando ejecuté ClassB
, pude ver que estaba usando los valores anteriores, no los nuevos. ¡Tuve que recompilar ClassB
para que utilizara nuevos valores de ClassA
! (¡Tuve que recompilar otras clases que importan ClassA
!)
¿Es esto solo por JDK 1.6 o debería haber sabido antes para recompilar ClassB
también! Iluminame. :)
¿Por qué intentas compilar las clases individualmente?
Usa un sistema de compilación como maven o ant o simplemente deja que tu IDE lo haga.
Lo único seguro es recompilar cada java que depende de una clase java que ha cambiado hasta que todas las clases que podrían efectuarse hayan sido compiladas nuevamente.
Es un problema de compatibilidad binaria. Las referencias a campos constantes se resuelven en tiempo de compilación. El comportamiento que estás viendo es correcto; si cambia los valores en la clase A, tendrá que volver a compilar el cliente (clase B). Para evitar estos problemas, considere agregar constantes utilizando un tipo de enumeración, introducido en la versión 5.0 de Java.
Si los valores de las variables final
de la clase ClassA
resultan constantes de tiempo de compilación, el compilador podría haberlos insertado en las clases utilizando ClassA
lugar de generar una referencia en tiempo de ejecución. Creo que esto es lo que sucedió en el caso que describiste.
Ejemplo:
public class Flags {
public static final int FOO = 1;
public static final int BAR = 2;
}
public class Consumer {
public static void main(String[] args) {
System.out.println(Flags.FOO);
}
}
En este ejemplo, el compilador probablemente incorporará el valor de FOO
en el código generado para Consumer
lugar de generar la referencia de tiempo de ejecución equivalente. Si el valor de FOO
cambia más adelante, tendrá que volver a compilar Consumer
para que use el nuevo valor.
Esta es una optimización, que tiene algunas ventajas con respecto a la eficiencia y la velocidad del programa compilado. Por ejemplo, al subrayar el valor, es posible habilitar más optimizaciones en las expresiones que lo utilizan, por ejemplo:
int x = Flags.FOO * 10;
En este ejemplo, al subrayar el valor (aquí: 1), el compilador puede observar que la multiplicación no hace ninguna diferencia y puede omitirse por completo.
Si no está utilizando los valores en un cambio, puede hacerlo en su lugar:
public class A
{
public static final int FOO;
public static final String BAR;
static
{
FOO = 42;
BAR = "Hello, World!";
}
}
entonces el compilador ya no codificará los valores en las otras clases que los están usando.
Supongamos que ClassA se ve así:
public class ClassA {
public static final int FOO = 1;
public static final int BAR = 2;
}
Si lo vuelve a compilar, ClassB continuará usando los valores anteriores. Supongo que podría depender del compilador, pero creo que este es el comportamiento típico. Si no quiere volver a compilar ClassB cada vez que cambia una constante en ClassA, tendrá que hacer algo como esto:
public class ClassA {
public static final int FOO = CONST(1);
public static final int BAR = CONST(2);
public static int CONST(int i) { return i; }
}
Porque ahora javac no está dispuesto a alinear las constantes. En su lugar, llamará al método CONST (int) cuando se ejecuta el inicializador estático de ClassA.