String é uma classe imutável em Java. Uma classe imutável é simplesmente uma classe cujas instâncias não podem ser modificadas. Por que a linguagem de programação Java escolhe tornar objetos da classe String imutáveis?
String é uma classe imutável em Java. Uma classe imutável é simplesmente uma classe cujas instâncias não podem ser modificadas. Por que a linguagem de programação Java escolhe tornar objetos da classe String imutáveis?
Respostas:
Esse problema está fortemente ligado à noção do que significa ser uma instância de uma classe. Em termos estritamente orientados a objetos, uma classe tem um invariante associado: um predicado que sempre é verdadeiro ao sair de um método (público) da classe. Essa noção é central para garantir que a herança seja bem definida, por exemplo (faz parte do Princípio de Substituição de Liskov ).
Um dos problemas mais perniciosos do Java é que é difícil impedir que o código do cliente quebre invariantes de classe.
Por exemplo, considere a seguinte classe 'ZipCode':
class ZipCode {
private String zipCode;
public ZipCode(String value){
if(!isValidZipCode(value))
throw new IllegalArgumentException();
zipCode = value;
assert(invariant());
}
public String get() { return zipCode; }
public boolean invariant() {
return isValidZipCode( zipCode );
}
}
Se String não fosse imutável, seria possível para um usuário do ZipCode chamar 'get' e alterar os caracteres a qualquer momento subsequente, quebrando assim o invariável e destruindo a integridade conceitual oferecida pelo encapsulamento do conceito do ZipCode.
Como esse tipo de integridade é essencial para garantir a validade de grandes sistemas, essa resposta à sua pergunta realmente implica em:
"Por que o Java não suporta um analógico do C ++ const, ou pelo menos oferece versões imutáveis de mais de suas classes de bibliotecas?"
Coisas como strings e datas são naturalmente valores. Em termos de C ++, esperamos que eles tenham um construtor de cópias, um operador de atribuição e um operador de igualdade, mas nunca esperamos usar o endereço deles. Portanto, não esperamos que eles sejam alocados individualmente no heap. Métodos virtuais não fazem sentido.
Objetos de domínio são naturalmente referências. Os C ++ não têm construtor de cópias, operador de atribuição ou operador de igualdade (eles são iguais apenas se forem idênticos). Podemos pegar o endereço deles e esperamos que eles sejam alocados em heap. Métodos são geralmente virtuais.
Java não possui classes de valor, apenas classes de referência. Os valores são falsificados com objetos imutáveis. Isso é verdade para seqüências de caracteres, mas não, infelizmente, para datas. A mutabilidade das datas Java causou problemas frequentes e agora está obsoleta. Valores mutáveis não podem ser usados como base para um hash, por exemplo.
O Java foi projetado para permitir a execução de subseções do código de um programa em ambientes com restrições de segurança. A maneira como esse requisito foi implementado foi definir um "SecurityManager" em um thread que tenha acesso aos parâmetros de certas operações críticas (por exemplo, abrir um arquivo) e perguntar se a operação deve ou não ser executada. Se o Java Strings fosse mutável, um programa poderia contornar essas restrições criando dois threads, um que executava uma operação de arquivo aberto que seria permitida enquanto o outro modificava a string em que armazenava o nome do arquivo em um que não seria permitido. Existe a possibilidade de o gerenciador de segurança ler a string original, aceitar a operação, que será transmitida para o código de abertura do arquivo que precederia a abertura do segundo arquivo (não permitido).
A última possibilidade tornaria todas essas operações mais lentas e seria mais provável que a implementação contivesse bugs; portanto, o uso de strings imutáveis foi a decisão mais sensata.
De maneira mais geral, objetos imutáveis são úteis porque permitem o compartilhamento sem a necessidade de fazer cópias defensivas (o que pode ser necessário mesmo em códigos não críticos à segurança para evitar erros quando os dados de origem são alterados); portanto, mesmo sem esse requisito, a decisão ainda seria razoável.