Question

I caractéristiques java vraiment admirent et je ne veux pas renoncer à l'utiliser pour le prochain problème:

J'ai une classe qui pourrait être hérité, et à l'intérieur de celui-ci est un private ArrayList arr; donc la fonction setter est ok, mais la fonction getter return arr; retourne la référence à cette variable toute personne capable d'éditer ce tableau l'ensemble que je ne suis pas veulent privé et ne serait pas de sens!

En C ++, je voudrais juste return const arr; et il retournerait référence constante à la variable.

Je tellement besoin la variable de ne pas être cloné ou copié manuellement parce qu'il ya tant de calculs qui nécessitent à (lecture seule la variable) POURQUOI il n'y a pas const en java ???? retournaient est-il possible que je pourrais échapper à la copie?

p.s (final ArrayList<Integer> arr;) est pas une option cause de ce tableau change toujours des valeurs de taille ou de l'élément.

Si je ne pouvais pas trouver une solution que je suis menacé de revenir à C ++ ou tout public à faire et vous ne devriez jamais obtenir mon logiciel: D


EDIT: une question plus importante: Suis-je demander quelque chose qui est pas bon (génie logiciel sage) Je veux dire que si les créateurs JAVA pensé de ne pas avoir référence const (retour Lecture seule référence), alors je dois demander quelque chose qui peut être manipulés d'une autre manière. ou ma conception du programme est mal, je suis tellement confus.

Était-ce utile?

La solution

Enveloppez la valeur de retour avec java.util.Collections.unmodifiableList . Il ne fait pas de copie des données, mais enveloppe la liste sous-jacente à la liste initiale, et les délégués des opérations en lecture seule. Les opérations qui modifieraient la liste sont rejetées lors de l'exécution via UnsupportedOperationException.

Votre

return arrayList;

devient

return Collections.unmodifiableList(arrayList);

Malheureusement, les contraintes de lecture seule ne sera pas appliquée par le compilateur. Ils seront toutefois être appliquées lors de l'exécution.

Vous avez également à votre disposition: unmodifiableMap , unmodifiableCollection , unmodifiableSortedSet et unmodifiableSortedMap . Et si cela ne suffit pas, vous pouvez toujours nous inspirer de cette approche de conception générale et créer votre propre lecture seule enveloppe classes.

Autres conseils

:) Vous avez plusieurs options:

  • Ne pas exposer getter, ne fournissent que des méthodes qui sont autorisés à appeler, par exemple.

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

  • Retour objet immuable:

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

Vous pouvez également utiliser Google Goyave est immuable collections . Dans ce cas, vous stocker un ImmutableList dans votre domaine.

Bien sûr, si les besoins de votre classe pour modifier cette liste en interne, en utilisant ImmutableList peut se révéler une mauvaise idée, puisque vous aurez besoin de créer une nouvelle instance de ImmutableList et réattribuer à la terrain chaque fois ...

Mais il est parfait quand vous savez que la liste ne changera pas après la construction de l'objet.

Exemple Immuable (liste ne changera pas après la construction de l'objet)

@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;
    }
}

Exemple Mutable (liste ne peut être modifié en utilisant le dispositif de réglage)

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);
    }
}

Remarques

  • Je sais qu'il est souvent conseillé aux méthodes de faire revenir le type le plus générique possible (de List dans ce cas), mais je préfère déclarer le type de retour de mon getter comme ImmutableList, car il agit comme documentation (pas besoin de documenter les années de liste retour immuabilité dans le Javadoc) et comme un contrat API. Il est comme dire « I garantie que cette liste soit immuable, vous n'avez pas à vous inquiéter ou une copie défensive qu'il ». Et il est très concis.
  • ImmutableList.copyOf() est grande, car il rejette automatiquement les listes nulles (en jetant NullPointerException). Il rejette également des éléments nuls. Et il ne sera pas copier la liste des sources si elle est déjà un ImmutableList, ce qui évite instanciation d'objets inutiles.
  • Dans le second exemple, j'initialiser le champ à un ImmutableList vide à l'aide ImmutableList.of(), parce qu'il est une bonne pratique de retourner les collections vides au lieu des valeurs nulles ( Null modèle objet ). Vous pourriez penser que cela crée un objet inutile instanciation, mais ImmutableList.of() retourne en fait un singleton.

Il existe une alternative à la méthode unmodifiableList. Vous pouvez simplement retourner une copie de ce tableau privé. Par exemple,

    return your_private_array.clone();

Eh bien, il pourrait y avoir une pénalité de performance pour cela. Mais vous avez une interface inchangée (vous revenez encore un tableau).

unmodifiableList est sans aucun doute la réponse.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top