¿Todas las constantes en tiempo de compilación están en línea?


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 de mi aplicación están usando estas opciones. Ahora, quiero cambiar una de las opciones solo 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 deshabilitar el revestimiento interno de las constantes de tiempo de compilación?

Author: Chris Cudmore, 2008-12-18

6 answers

Puede usar String.intern() para obtener el efecto deseado, pero debe comentar su código, porque no mucha gente sabe acerca de esto. es decir,

public static final String configOption1 = "some option".intern();

Esto evitará el tiempo de compilación en línea. Dado que se refiere a la misma cadena exacta que el compilador colocará en el perm, no está creando nada extra.

Como alternativa, siempre puedes hacer

public static final String configOption1 = "some option".toString();

Sin embargo esto no usará la cadena interna compilada, creará una nueva en la vieja generación. gran gran cosa, y podría ser más fácil de leer. De cualquier manera, ya que esto es un poco extraño, debe comentar el código para informar a los que lo mantienen lo que está haciendo.

Editar: Encontramos otro enlace SO que da referencias a la JLS, para más información sobre esto. Cuándo usar intern () en literales de cadena

 26
Author: reccles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:30:47

No, es parte de la JLS, me temo. Esto se toca, brevemente, en los Puzzles de Java, 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

 10
Author: GaryF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:23:03

No. Sin embargo, podría reemplazarlos con una llamada a un método estático, como:

class ApplicationDefs {

    public static String configOption1() { return "some option"; }

}

Concedido, no es hermoso pero cumpliría su requisito. :)

 7
Author: Bombe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:24:34

En realidad, si elimina la palabra clave final las constantes dejan de ser constantes en tiempo de compilación y entonces su configuración funcionará como desee.

Sin embargo, se sugiere fuertemente que si esto es de hecho algún tipo de configuración que está tratando de hacer, debe moverse a una forma más manejable que las constantes en algún archivo de clase.

 7
Author: Yuval Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:46:11

Puede inhibir la inserción haciendo que sus constantes no sean constantes de tiempo de compilación...

Por ejemplo, null no es una constante de tiempo de compilación. Cualquier expresión que involucre una constante de tiempo de compilación no es una constante de tiempo de compilación, aunque javac puede hacer plegamiento constante dentro de la unidad de compilación.

public static final String configOption1 = null!=null?"": "some option";
 6
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 15:04:57

No hay nada aquí que diga que estos valores deben estar en línea. Usted está declarando algunos public, static miembros. Esas otras clases están usando los valores de estos miembros. No se pide ninguna entrada. Incluso la palabra clave final

Pero por razones de rendimiento , algunas JVM pueden inline estos valores en esas otras clases. Esto es una optimización. Ninguna optimización debería cambiar el comportamiento de un programa. Así que si cambias la definición de estos miembros, la JVM debería des-inline los valores anteriores.

Esta es la razón por la que no hay manera de desactivar la inserción. O bien la JVM no está en línea y no hay ningún problema o si está en línea, la JVM garantiza que no esté en línea.

No estoy seguro de lo que sucede cuando se importa estáticamente esta clase. Creo (no estoy seguro) que la inserción se realiza y puede causar los problemas que mencionas. Si ese es el caso, básicamente podría eliminar la importación estática y está bien.

 -4
Author: Pierre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:38:46