Imagine que eu tenho essa classe:
public class Test
{
private String[] arr = new String[]{"1","2"};
public String[] getArr()
{
return arr;
}
}
Agora, eu tenho outra classe que usa a classe acima:
Test test = new Test();
test.getArr()[0] ="some value!"; //!!!
Portanto, este é o problema: eu acessei um campo privado de uma classe de fora! Como posso evitar isso? Quero dizer, como posso tornar esse array imutável? Isso significa que, com todo método getter, você pode trabalhar para acessar o campo privado? (Não quero bibliotecas como o Guava. Só preciso saber a maneira correta de fazer isso).
final
faz evitar a modificação do campo . No entanto, impedir a modificação doObject
referido por um campo é mais complicado.Respostas:
Você deve retornar uma cópia da sua matriz.
fonte
Unmodifiable List
.Se você pode usar uma Lista em vez de uma matriz, Coleções fornece uma lista não modificável :
fonte
Collections.unmodifiableList(list)
como atribuição ao campo, para garantir que a lista não seja alterada pela própria classe.String
são, mas se forem mutáveis, pode ser necessário fazer algo para impedir que o chamador as altere.O modificador
private
protege apenas o próprio campo de ser acessado de outras classes, mas não as referências de objeto por esse campo. Se você precisar proteger um objeto referenciado, simplesmente não o divulgue. mudançapara:
ou para
fonte
O
Collections.unmodifiableList
já foi mencionado - oArrays.asList()
estranhamente não! Minha solução também seria usar a lista de fora e agrupar a matriz da seguinte maneira:O problema de copiar a matriz é: se você estiver fazendo isso toda vez que acessar o código e a matriz for grande, criará muito trabalho para o coletor de lixo, com certeza. Portanto, a cópia é uma abordagem simples, mas muito ruim - eu diria "barato", mas com muita memória! Especialmente quando você está tendo mais do que apenas 2 elementos.
Se você olhar para o código fonte
Arrays.asList
eCollections.unmodifiableList
realmente não houver muito criado. O primeiro apenas quebra a matriz sem copiá-la, o segundo apenas quebra a lista, tornando as alterações indisponíveis.fonte
immutableList
até o fim!Arrays.asList
eCollections.unmodifiableList
são provavelmente mais baratas para matrizes maiores. Talvez alguém possa calcular quantos elementos são necessários, mas eu já vi código em for-loops com matrizes contendo milhares de elementos sendo copiados apenas para evitar modificações - isso é insano!Você também pode usar o
ImmutableList
que deve ser melhor que o padrãounmodifiableList
. A classe faz parte das bibliotecas do Guava criadas pelo Google.Aqui está a descrição:
Aqui está um exemplo simples de como usá-lo:
fonte
Test
classe para deixar a lista retornada inalterada . Você precisa garantir queImmutableList
seja retornado e que os elementos da lista também sejam imutáveis. Caso contrário, minha solução também deve ser segura.Neste ponto de vista, você deve usar a cópia da matriz do sistema:
fonte
clone
e não é tão conciso.Você pode retornar uma cópia dos dados. O chamador que optar por alterar os dados estará alterando apenas a cópia
fonte
O problema do problema é que você está retornando um ponteiro para um objeto mutável. Opa Você torna o objeto imutável (a solução de lista não modificável) ou retorna uma cópia do objeto.
Em geral, a finalidade dos objetos não protege os objetos de serem alterados se forem mutáveis. Esses dois problemas são "beijar primos".
fonte
Retornar uma lista não modificável é uma boa idéia. Mas uma lista que não é modificável durante a chamada para o método getter ainda pode ser alterada pela classe ou classes derivadas da classe.
Em vez disso, você deve deixar claro para quem estende a classe que a lista não deve ser modificada.
Portanto, no seu exemplo, isso pode levar ao seguinte código:
No exemplo acima, tornei o
STRINGS
campo público. Em princípio, você pode acabar com a chamada do método, pois os valores já são conhecidos.Você também pode atribuir as strings a um
private final List<String>
campo que não pode ser modificado durante a construção da instância da classe. O uso de argumentos constantes ou de instanciação (do construtor) depende do design da classe.fonte
Sim, você deve retornar uma cópia da matriz:
fonte