Desde que soube que a classe java.lang.String
é declarada como final em Java, fiquei me perguntando por que isso acontece. Não encontrei nenhuma resposta na época, mas este post: Como criar uma réplica da classe String em Java? me lembrou da minha consulta.
Claro, o String fornece toda a funcionalidade que eu sempre precisei e nunca pensei em nenhuma operação que exigiria uma extensão da classe String, mas você nunca saberá do que alguém pode precisar!
Então, alguém sabe qual era a intenção dos designers quando decidiram torná-lo final?
Respostas:
É muito útil ter cadeias implementadas como objetos imutáveis . Você deve ler sobre imutabilidade para entender mais sobre isso.
Uma vantagem de objetos imutáveis é que
( daqui ).
Se String não fosse final, você poderia criar uma subclasse e ter duas seqüências parecidas quando "vistas como Strings", mas na verdade são diferentes.
fonte
Este é um bom artigo que descreve dois motivos já mencionados nas respostas acima:
E esse provavelmente é o comentário mais detalhado nesse artigo. Tem a ver com o pool de strings em Java e questões de segurança. É sobre como decidir o que entra no pool de strings. Supondo que as duas seqüências de caracteres sejam iguais se a sequência de caracteres for a mesma, teremos uma condição de corrida para quem chegar lá primeiro e, juntamente com isso, problemas de segurança. Caso contrário, o conjunto de cadeias conterá cadeias redundantes, perdendo a vantagem de tê-lo em primeiro lugar. Basta ler por si mesmo, sim?
Estender String causaria estragos com iguais e estagiários. JavaDoc diz que é igual a:
Supondo que
java.lang.String
não fosse final, aSafeString
poderia ser igual aString
e vice-versa; porque eles representariam a mesma sequência de caracteres.O que aconteceria se você se inscrevesse
intern
em umSafeString
- entrariaSafeString
no conjunto de cadeias de caracteres da JVM? OsClassLoader
objetos e todos os objetos às quais asSafeString
referências retidas seriam bloqueados durante a vida útil da JVM. Você obteria uma condição de corrida sobre quem poderia ser o primeiro a estagiar uma sequência de personagens - talvez vocêSafeString
ganhasse, talvez umString
, ou talvez umSafeString
carregado por um carregador de classe diferente (portanto, uma classe diferente).Se você vencesse a corrida na piscina, este seria um verdadeiro singleton e as pessoas poderiam acessar todo o seu ambiente (sandbox) através de reflexão e
secretKey.intern().getClass().getClassLoader()
.Ou a JVM poderia bloquear esse furo, certificando-se de que apenas objetos String concretos (e nenhuma subclasse) fossem adicionados ao pool.
Se igual foi implementado de forma que
SafeString
! =String
EntãoSafeString.intern
! =String.intern
, ESafeString
teria que ser adicionado ao pool. A piscina se tornaria uma piscina em<Class, String>
vez de<String>
e tudo o que você precisaria para entrar na piscina seria um novo carregador de classe.fonte
O motivo absolutamente mais importante pelo qual String é imutável ou final é que ele é usado pelo mecanismo de carregamento de classe e, portanto, possui aspectos de segurança profundos e fundamentais.
Se String fosse mutável ou não final, uma solicitação para carregar "java.io.Writer" poderia ter sido alterada para carregar "mil.vogoon.DiskErasingWriter"
reference: Por que String é imutável em Java
fonte
String
é uma classe muito essencial em Java, muitas coisas dependem dele para funcionar de certa maneira, por exemplo, ser imutável.Fazer a classe
final
evita subclasses que podem quebrar essas suposições.Observe que, mesmo agora, se você usar reflexão, poderá quebrar Strings (alterar seu valor ou código de hash). A reflexão pode ser interrompida com um gerente de segurança. Se
String
não fossefinal
, todos poderiam fazê-lo.Outras classes que não são declaradas
final
permitem definir subclasses um pouco quebradas (você pode ter umaList
que acrescente à posição errada, por exemplo), mas pelo menos a JVM não depende daquelas para suas operações principais.fonte
final
em uma classe não garante imutabilidade. Apenas garante que os invariantes de uma classe (um dos quais pode ser imutável) não podem ser alterados por uma subclasse.Como Bruno disse, é sobre imutabilidade. Não se trata apenas de Strings, mas também de quaisquer invólucros, como Double, Inteiro, Caractere, etc. Há muitas razões para isso:
Basicamente, para que você, como programador, tenha certeza de que sua string nunca será alterada. Além disso, se você souber como funciona, pode melhorar o gerenciamento de memória. Tente criar duas seqüências idênticas uma após a outra, por exemplo "olá". Você notará, se você depurar, que eles têm IDs idênticos, isso significa que eles são exatamente OS MESMOS objetos. Isso se deve ao fato de o Java permitir que você faça isso. Isso não seria possível se as cordas fossem mutáveis. Eles podem ter o mesmo que eu etc., porque nunca mudarão. Portanto, se você decidir criar 1.000.000 de strings "olá", o que você realmente faria é criar 1.000.000 de ponteiros para "olá". Além disso, alocar qualquer função na string ou qualquer invólucro por esse motivo resultaria na criação de outro objeto (observe novamente o ID do objeto - ele será alterado).
Adicionalmente final em Java não significa necessariamente que o objeto não pode ser alterado (é diferente, por exemplo, do C ++). Isso significa que o endereço para o qual ele aponta não pode ser alterado, mas você ainda pode alterar suas propriedades e / ou atributos. Portanto, entender a diferença entre imutabilidade e final em alguns casos pode ser realmente importante.
HTH
Referências:
fonte
Pode ter sido para simplificar a implementação. Se você projetar uma classe que será herdada pelos usuários da classe, terá um novo conjunto de casos de uso a serem considerados no design. O que acontece se eles fizerem isso ou aquilo com o campo protegido por X? Para finalizar, eles podem se concentrar em fazer com que a interface pública funcione corretamente e garantir que ela seja sólida.
fonte
Com muitos pontos positivos já mencionados, gostaria de acrescentar outro - um dos motivos pelos quais String é imutável em Java é permitir que String armazene em cache seu código de hash , sendo imutável String em Java armazena em cache seu código de hash e não calcula todos os No momento, chamamos o método hashcode de String , o que o torna muito rápido como chave hashmap para ser usado no hashmap em Java.
Em resumo, porque String é imutável, ninguém pode alterar seu conteúdo depois de criado, o que garante que o hashCode de String seja o mesmo em várias chamadas.
Se você vir a
String
classe has é declarada comoe
hashcode()
função é a seguinte -Se já é computador, basta retornar o valor.
fonte
Para garantir uma melhor implementação. Obviamente, deveria ter sido uma interface.
[edit] Ah, obtendo mais votos sem noção. A resposta é perfeitamente séria. Eu tive que programar meu caminho em torno da implementação estúpida de String várias vezes, levando a um desempenho severo e perda de produtividade
fonte
Além dos motivos óbvios sugeridos em outras respostas, um pensamento de tornar a classe String final também pode estar relacionada à sobrecarga de desempenho dos métodos virtuais. Lembre-se de que String é uma classe pesada, tornando isso final, significa nenhuma sub-implementação, com certeza, significa que não há nenhuma chamada indireta de sobrecarga. É claro que agora temos coisas como invocação virtual e outras, que sempre fazem esse tipo de otimização para você.
fonte
Além dos motivos mencionados em outras respostas (segurança, imutabilidade, desempenho), deve-se notar que
String
possui suporte especial ao idioma. Você pode escreverString
literais e há suporte para o+
operador. Permitir que os programadores subclassesString
incentivaria hacks como:fonte
Bem, eu tenho um pensamento diferente, não tenho certeza se estou correto ou não, mas em Java String é o único objeto que pode ser tratado como um tipo de dados primitivo, bem, quero dizer que podemos criar um objeto String como String name = "java " . Agora, como outros tipos de dados primitivos que são copiar por valor, não copiar por referência, espera-se que o String tenha o mesmo comportamento, por isso o String é final. Isso é o que o meu pensamento. Por favor, ignore se é completamente ilógico.
fonte
A finalidade das strings também as defende como padrão. No C ++, você pode criar subclasses de string, para que cada loja de programação possa ter sua própria versão de string. Isso levaria à falta de um padrão forte.
fonte
Digamos que você tenha uma
Employee
classe que tenha um métodogreet
. Quando ogreet
método é chamado, ele simplesmente imprimeHello everyone!
. Então esse é o comportamento esperado dogreet
métodoAgora, deixe a
GrumpyEmployee
subclasseEmployee
e substitua ogreet
método, como mostrado abaixo.Agora, no código abaixo, dê uma olhada no
sayHello
método Ele toma aEmployee
instância como um parâmetro e chama o método greet, esperando que ele digaHello everyone!
Mas o que obtemos éGet lost!
. Essa mudança de comportamento se deve aEmployee grumpyEmployee = new GrumpyEmployee();
Esta situação pode ser evitada se a
Employee
aula foi feitafinal
. Agora depende da sua imaginação a quantidade de caos que um programador atrevido poderia causar se aString
Classe não fosse declarada comofinal
.fonte
A JVM sabe o que é imutável? A resposta é Não, o pool constante contém todos os campos imutáveis, mas todos os campos / objetos imutáveis não são armazenados apenas no pool constante. Somente nós o implementamos de maneira a alcançar a imutabilidade e seus recursos. CustomString poderia ser implementado sem torná-lo final usando MarkerInterface, o que forneceria um comportamento especial do java para seu pool, o recurso ainda é aguardado!
fonte
A maioria das respostas está relacionada à imutabilidade - por que um objeto do tipo String não pode ser atualizado no local. Há muita discussão boa aqui, e a comunidade Java faria bem em adotar a imutabilidade como principal. (Não prendo a respiração.)
No entanto, a pergunta do OP é sobre por que é final - por que não pode ser estendida. Alguns aqui aceitaram isso, mas eu concordaria com o OP de que existe uma lacuna real aqui. Outro idioma permite que os desenvolvedores criem novos tipos nominais para um tipo. Por exemplo, em Haskell, posso criar os seguintes novos tipos que são idênticos em tempo de execução como texto, mas fornecem segurança de ligação em tempo de compilação.
Então, eu apresentaria a seguinte sugestão como um aprimoramento da linguagem Java:
(Ou talvez possamos começar a nos livrar do Java)
fonte
Se você criar uma string uma vez. Considerará que é um objeto se você deseja modificar isso; não é possível; ele criará um novo objeto.
fonte