java - ¿Están todas las constantes de tiempo de compilación en línea?
inlining compile-time-constant (6)
Digamos que tengo una clase como esta:
class ApplicationDefs{
public static final String configOption1 = "some option";
public static final String configOption2 = "some other option";
public static final String configOption3 = "yet another option";
}
Muchas de las otras clases en mi aplicación están usando estas opciones. Ahora, quiero cambiar solo una de las opciones e implementar solo la clase compilada. Pero si estos campos están alineados en las clases de consumidores, esto se vuelve imposible, ¿verdad?
¿Hay alguna opción para desactivar el forro de las constantes de tiempo de compilación?
En realidad, si elimina la palabra clave final
las constantes dejan de ser constantes en tiempo de compilación y luego su configuración funcionará como usted desee.
Sin embargo, se recomienda encarecidamente que si esto es de hecho algún tipo de configuración que está tratando de hacer, debe pasar a una forma más manejable que las constantes en algún archivo de clase.
No hay nada aquí que diga que estos valores deben estar en línea. Usted acaba de declarar algunos miembros public
, static
. Esas otras clases están usando los valores de estos miembros. No se solicita la inclusión. Incluso la palabra clave final
Pero por razones de rendimiento , algunas JVM pueden alinear estos valores en esas otras clases. Esta es una optimización. Ninguna optimización debería cambiar el comportamiento de un programa. Entonces, si cambia la definición de estos miembros, la JVM debe desanudar los valores anteriores.
Esta es la razón por la cual no hay forma de desactivar el enlining. O bien la JVM no está en línea y no hay ningún problema, o si está en línea, la JVM garantiza la desinserción.
No estoy seguro de lo que sucede cuando importa estáticamente esta clase. Creo (no estoy seguro) que la alineación se realiza y puede causar los problemas que mencionas. Si ese es el caso, básicamente puedes eliminar la importación estática y estás bien.
No, es parte de JLS, me temo. Esto se menciona brevemente en Java Puzzlers, pero no tengo mi copia a mano.
Supongo que podría considerar tener estas constantes definidas en un archivo de propiedades, y tener la clase que las carga periódicamente.
Referencia: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313
No. Sin embargo, podrías reemplazarlos con una llamada a un método estático, como:
class ApplicationDefs {
public static String configOption1() { return "some option"; }
}
De acuerdo, no es hermoso, pero cumpliría tus requisitos. :)
Puede inhibir la creación haciendo sus constantes de tiempo constantes de no compilación ...
Por ejemplo, null
no es una constante de tiempo de compilación. Cualquier expresión que implique una constante de tiempo no de compilación no es una constante de tiempo de compilación, aunque javac puede doblar constantemente dentro de la unidad de compilación.
public static final String configOption1 = null!=null?"": "some option";
Puede utilizar String.intern () para obtener el efecto deseado, pero debe comentar su código, porque no muchas personas lo saben. es decir
public static final String configOption1 = "some option".intern();
Esto evitará que el tiempo de compilación esté en línea. Como se refiere exactamente a la misma cadena que el compilador colocará en la permanente, no está creando nada extra.
Como alternativa, siempre puedes hacer
public static final String configOption1 = "some option".toString();
sin embargo, esto no usará la secuencia interna compilada, sino que creará una nueva en la vieja generación. No es un gran problema, y podría ser más fácil de leer. De cualquier manera, ya que esto es un poco extraño, deberías comentar el código para informar a aquellos que lo mantienen lo que estás haciendo.
Editar: Encontré otro enlace SO que da referencias al JLS, para obtener más información al respecto. Cuándo usar intern () en literales de cadena