Frage

ich wirklich bewundere Java-Funktionen und ich will nicht für das nächste Problem mit, es aufzugeben:

Ich habe eine Klasse, die vererbt werden kann, und in der es eine private ArrayList arr; also die Setter-Funktion in Ordnung ist, aber die Funktion Getter return arr; gibt die Referenz auf diese Variable, die jeder der Lage, bearbeitet, die ganze Reihe, die ich nicht tun will und privaten würde keinen Sinn machen!

In C ++ würde ich nur return const arr; und es wäre konstanten Verweis auf die Variable zurück.

Ich brauche so viel die Variable nicht geklont oder manuell kopiert werden, weil es so viele Berechnungen sind, die (nur die Variable READ) erfordern, warum es keine const in Java Rückkehr ???? gibt es eine Möglichkeit, das Kopieren entkommen konnte?

P. S (final ArrayList<Integer> arr;) ist keine Option, weil das Array immer Größe oder Elementwerte ändert.

Wenn ich könnte nicht ein Update finden, dass ich droht C zurück zu gehen ++ oder machen alles öffentlich und Sie sollten nie meine Software bekommen: D


EDIT: eine weitere wichtige Frage: Bin ich für etwas zu fragen, die nicht gut ist (Software-Engineering weise) Ich meine, wenn JAVA Schöpfer gedacht nicht konstante Referenz mit (Rückkehr lesen Referenzen nur) dann muss ich nach etwas fragen, das sein kann in anderer Weise behandelt. oder mein Programm-Design ist falsch, ich bin so verwirrt.

War es hilfreich?

Lösung

Wickeln Sie den Rückgabewert mit java.util.Collections.unmodifiableList . Sie stellen keine Kopie der Daten, sondern wickelt die ursprüngliche Liste, und die Delegierten Nur-Lese-Operationen auf die zugrunde liegende Liste. Operationen, die die Liste ändern würden, werden zur Laufzeit über UnsupportedOperationException abgelehnt.

Sie

return arrayList;

wird

return Collections.unmodifiableList(arrayList);

Leider ist die Nur-Lese-Einschränkungen nicht vom Compiler erzwungen werden. Sie werden jedoch zur Laufzeit durchgesetzt werden.

Sie haben auch Ihnen zur Verfügung: unmodifiableMap , unmodifiableCollection , unmodifiableSortedSet und unmodifiableSortedMap . Und wenn diese nicht ausreichen, können Sie immer noch Inspiration von diesem allgemeinen Design-Ansatz nehmen, und erstellen Sie Ihre eigenen benutzerdefinierten schreibgeschützten Wrapper-Klassen.

Andere Tipps

:) Sie haben mehrere Möglichkeiten:

  • Do not aussetzen Getter, bietet nur Methoden, die auf Anruf erlaubt sind, z.

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

  • Zurück unveränderliches Objekt:

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

Sie können auch benutzen Google Guava ist unveränderlich Sammlungen . In diesem Fall würden Sie ein ImmutableList in Ihrem Bereich.

Natürlich, wenn Ihre Klasse Bedürfnisse dieser Liste intern zu modifizieren, ImmutableList mit Macht sich als eine schlechte Idee zu sein, da Sie eine neue ImmutableList Instanz erstellen brauchen werden, und weisen Sie es an die Feld jedes Mal ...

Aber es ist perfekt, wenn Sie wissen, dass die Liste nicht nach Objektbau ändern.

Immutable Beispiel (Liste nicht nach Objektbau ändern)

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

Mutable Beispiel (Liste nur dann geändert werden, um die Setter verwenden)

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

Hinweise

  • Ich weiß, dass es oft ist ratsam zu machen Methoden, um die allgemeinste Art möglich (List in diesem Fall) zurückkehren, aber ich ziehe meine Getter Rückkehr Typ als ImmutableList zu erklären, weil sie als Dokumentation wirkt (keine Notwendigkeit, die zurückgegebene Liste der dokumentieren Unveränderbarkeit im Javadoc-) und als einen API-Vertrag. Es ist wie wenn man sagt: „Ich Garantie diese Liste unveränderlich sein, müssen Sie sich keine Sorgen machen oder defensiv kopieren“. Und es ist sehr prägnant.
  • ImmutableList.copyOf() ist groß, da sie automatisch null Listen ablehnt (von NullPointerException werfen). Sie lehnt auch null Elemente. Und es wird die Quellenliste nicht kopieren, wenn es schon ein ImmutableList, die nutzlos Objektinstanziierung vermeidet.
  • Im zweiten Beispiel, ich initialisieren, das Feld zu einem leeren ImmutableList ImmutableList.of() verwenden, weil es eine gute Praxis ist leer Sammlungen statt Nullwerte zurück ( Null-Objekt Muster ). Man könnte denken, dass dies unnötig Objektinstanziierung schafft, aber ImmutableList.of() gibt tatsächlich einen Singleton.

Es gibt eine Alternative zum unmodifiableList Verfahren. Sie können nur eine Kopie dieser privaten Array zurück. Zum Beispiel:

    return your_private_array.clone();

Nun, es könnte eine Leistungseinbuße für diese sein. Aber Sie haben Schnittstelle unverändert (Sie noch ein Array zurück).

unmodifiableList ist definitiv die Antwort.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top