java string string-interning

java - Cuándo usar intern() en los literales de cadena



string string-interning (4)

Veo mucho código heredado como este:

class A { public static final String CONSTANT = "value".intern(); ... }

No veo ningún motivo para el interno (), ya que en el Javadoc se puede leer: "Todas las cadenas literales y las expresiones constantes de cadena están intercaladas". ¿Hay alguna intención de esto, tal vez en revisiones pasadas del lenguaje?


El uso de intern() con el literal constante de la cadena es una pérdida de tiempo, ya que el literal ya estará internado como se especifica en la sección de de la especificación de lenguaje Java® .

Citando de Java SE 8 Edition:

Además, un literal de cadena siempre se refiere a la misma instancia de clase String. Esto se debe a que los literales de cadena (o, más generalmente, las cadenas que son los valores de las expresiones constantes (§15.28)) son "internados" para compartir instancias únicas, utilizando el método String.intern.

Creo que el codificador no apreció este hecho.

Editar:

Como ha señalado, hay un impacto sobre cómo esta constante puede estar en línea.

- https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5


Esta es una técnica para asegurar que CONSTANT no sea en realidad una constante.

Cuando el compilador de Java ve una referencia a una primitiva estática final o Cadena, inserta el valor real de esa constante en la clase que lo utiliza. Si luego cambia el valor constante en la clase de definición pero no recompila la clase que usa, continuará usando el valor anterior.

Al llamar a intern () en la cadena "constante", el compilador ya no lo considera una constante estática, por lo que la clase en uso accederá al miembro de la clase definidora en cada uso.

Citas de JLS:


Hace un tiempo intervine () ed todas las cadenas procedentes de archivos de clase (para un analizador de archivos de clase). Intern () hizo que el programa utilizara menos memoria (no lo hará en este caso, como otros lo han señalado), pero ralentizó significativamente el programa (creo que tomó 4 segundos analizar todo rt.jar y ese cambio lo puso más de 8 segundos). Al analizarlo en ese momento (creo que era JDK 1.4), el código interno () es bastante feo y más lento que probablemente deba serlo.

Si tuviera que considerar llamar a intern () en mi código, primero lo perfilaría sin pasante () y luego lo perfilaría con interno () tanto para la memoria como para la velocidad y vería cuál es "peor" para el cambio.


He usado interno () para "bloqueo". Por ejemplo, digamos que tengo un "repositorio" de "registros comerciales". Mientras edito y actualizo una operación, quiero bloquear la operación; En su lugar, podría bloquear el tradeId.intern () para no tener que preocuparme por los clones de un comercio que esté flotando. No estoy seguro si a todos les gusta este uso.

Esto supone que es poco probable que el campo de identificación colisione accidentalmente con el campo de identificación de otro objeto de dominio: un tradeId no colisiona con account_number, por ejemplo, donde también podría estar haciendo

synchronized(account.getAccountNumber().intern()) {...}

ver example