Pergunta

Eu realmente admiro os recursos do Java e não quero desistir de usá -lo para o próximo problema:

Eu tenho uma aula que pode ser herdada e dentro dela é um private ArrayList arr; Portanto, a função do setter está ok, mas a função getter return arr; Retorna a referência à variável que qualquer pessoa capaz de editar toda a matriz que eu não quero e particular não faria sentido!

Em C ++ eu só faria return const arr; e retornaria referência constante à variável.

Eu preciso muito que a variável não seja clonada ou copiada manualmente, porque existem muitos cálculos que exigem (leia apenas a variável) por que não há constância de retorno em java ???? Existe alguma maneira de escapar da cópia?

ps (final ArrayList<Integer> arr;) Não é uma opção porque a matriz sempre altera os valores de tamanho ou elemento.

Se eu não consegui encontrar uma correção, estou ameaçando voltar ao C ++ ou tornar tudo público e você nunca deve obter meu software: D


EDIT: Mais uma pergunta importante: estou pedindo algo que não seja bom (em termos de engenharia de software), quero dizer, se os criadores do Java pensaram em não ter const referência (retornando apenas referências leituras), então devo estar pedindo algo que possa ser tratado em outros caminho. Ou o design do meu programa está errado, estou tão confuso.

Foi útil?

Solução

Embrulhe o valor de retorno com java.util.Collections.unmodifiablelist. Ele não faz uma cópia dos dados, mas envolve a lista original e delega operações somente leitura na lista subjacente. Operações que modificariam a lista são rejeitadas em tempo de execução via UnsupportedOperationException.

Sua

return arrayList;

torna-se

return Collections.unmodifiableList(arrayList);

Infelizmente, as restrições somente leitura não serão aplicadas pelo compilador. No entanto, eles serão aplicados em tempo de execução.

Você também tem disponível para você: Não modificável, não modificador, não modificadaBecollection, Não modificável, e não modificável e mapa. E se não forem suficientes, você ainda poderá se inspirar nesta abordagem de design geral e criar suas próprias classes de wrapper somente leitura personalizadas.

Outras dicas

:) Você tem várias opções:

  • Não exponha o getter, forneça apenas métodos que podem ligar, por exemplo,

    public void addToList(Object arg) { this.arr.add(arg);}

  • Retornar objeto imutável:

    public List getArr() { return Collections.unmodifiableList(this.arr); }

Você também pode usar Google goiabaé imutável Coleções. Nesse caso, você armazenaria um ImutableList em seu campo.

Obviamente, se sua classe precisar modificar esta lista internamente, usando imutableList poderia Torne -se a ser uma má idéia, já que você precisará criar uma nova instância imutablelist e reatribuir ao campo a cada vez ...

Mas é perfeito quando você sabe que a lista não mudará após a construção de objetos.

Exemplo imutável (a lista não mudará após a construção do objeto)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

Exemplo mutável (a lista pode ser modificada apenas usando o setter)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

Comentários

  • Eu sei que muitas vezes é aconselhável que os métodos retornem o tipo mais genérico possível (List nesse caso), mas prefiro declarar o tipo de retorno do meu getter como um ImmutableList, porque atua como documentação (não há necessidade de documentar a imutabilidade da lista devolvida no Javadoc) e como um contrato de API. É como dizer "eu garantia Essa lista é imutável, você não precisa se preocupar ou copiá -la defensivamente ". E é muito conciso.
  • ImmutableList.copyOf() é ótimo, pois rejeita automaticamente listas nulas (jogando NullPointerException). Também rejeita elementos nulos. E não copiará a lista de origem se já for um imutablelist, o que evita instanciação de objeto inútil.
  • No segundo exemplo, inicializo o campo para um imutableList vazio usando ImmutableList.of(), porque é uma boa prática devolver coleções vazias em vez de valores nulos (Padrão de objeto nulo). Você pode pensar que isso cria instanciação desnecessária do objeto, mas ImmutableList.of() Na verdade, retorna um singleton.

Há uma alternativa ao método não modificada. Você pode apenas retornar uma cópia desta matriz privada. Por exemplo,

    return your_private_array.clone();

Bem, pode haver uma penalidade de desempenho para isso. Mas você tem interface inalterada (você ainda retorna uma matriz).

não modificada é definitivamente a resposta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top