Quando usar estagiário () em literais de string
-
11-09-2019 - |
Pergunta
Eu vejo um monte de código legado como esta:
class A {
public static final String CONSTANT = "value".intern();
...
}
Eu não vejo nenhuma razão para o interno (), como no Javadoc pode ler: "Todos os strings literais e expressões constantes valorizado cordas estão internados" Existe alguma intenção deste, talvez em revisões anteriores da língua?
Solução
Esta é uma técnica para garantir que CONSTANT
não é realmente uma constante.
Quando o compilador Java vê uma referência a um static final primitivo ou String, ele insere o valor real do que constante para a classe que o utiliza. Se você alterar o valor constante na classe definindo mas não recompilar a classe usando, ele vai continuar a usar o valor antigo.
Ao chamar estagiário () na string "constante", ele não é mais considerado uma constante estático pelo compilador, então a classe usando realmente acessar o membro definição de classe em cada utilização.
JLS citações:
-
definição de uma constante de tempo de compilação: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#5313
-
implicação de mudanças para uma constante de tempo de compilação (cerca de metade da página): http://docs.oracle.com/javase/specs/jls/se6/html/binaryComp.html#45139
Outras dicas
O uso de intern()
com o literal string constante é um desperdício de tempo como o literal já será internado conforme especificado pela seção 3.10. 5. string literais de O Java® Specification Language .
Citando Java SE 8 Edição:
Além disso, uma cadeia de caracteres refere-se sempre ao mesmo exemplo de corda classe. Isso ocorre porque strings literais - ou, mais genericamente, cordas que são os valores das expressões constantes (§15.28) -. São "internado" para instâncias exclusivas de compartilhamento, usando o método String.intern
Eu acho que o codificador não apreciar este fato.
Editar:
Como kdgregory tem fora apontado há um impacto sobre a forma como esta constante pode ser embutido.
1 - https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls -3.10.5
Um tempo atrás eu estagiário () ed todas as cordas provenientes de arquivos de classe (para um analisador classfile). Intern () O ING fez o uso do programa menos memória (não neste caso, como outros apontaram), mas ele fez lento o programa para baixo significativamente (acho que demorou 4 segundos para analisar todos rt.jar e que a mudança colocá-lo mais de 8 segundos). Olhando para ele na época (foi JDK 1.4 eu acho) o estagiário () código é muito feio e mais lento que em provavelmente precisa ser.
Se eu fosse para considerar chamar estagiário () no meu código eu primeiro perfil sem estagiário () e, em seguida, o perfil com estagiário () tanto para a memória e velocidade e ver qual é o "pior" para a mudança.
Eu tenho usado estagiário () para "bloqueio". Por exemplo, digamos que eu tenho um "repositório" de "registros comerciais". Enquanto eu editar e atualizar um comércio que eu quero para bloquear o comércio; Eu poderia, em vez bloquear na tradeId.intern () para que eu não precisa se preocupar com clones de um comércio flutuando. Não estou certo se todo mundo gosta esse uso.
Isso pressupõe que o campo id é improvável que acidentalmente colidem com o campo id de outro objeto de domínio - um tradeId não acontece a colidir com ACCOUNT_NUMBER por exemplo, onde se pode também estar fazendo
synchronized(account.getAccountNumber().intern()) {...}
href="http://tshrestha.blogspot.com/2012/01/stringintern-and-concurrency.html"