Domanda

Ammiro davvero le funzionalità Java e non voglio rinunciare a usarlo per il prossimo problema:

Ho una classe che potrebbe essere ereditata e al suo interno c'è a private ArrayList arr; Quindi la funzione setter è ok, ma la funzione getter return arr; restituisce il riferimento a quella variabile che chiunque sia in grado di modificare l'intero array che non voglio e privato non avrebbe alcun senso!

In C++ lo farei semplicemente return const arr; e restituirebbe un riferimento costante alla variabile.

Ho tanto bisogno che la variabile non venga clonata o copiata manualmente perché ci sono così tanti calcoli che richiedono (LEGGERE SOLO la variabile) PERCHÉ non c'è nessun ritorno const in Java ????c'è un modo per evitare di copiare?

p.s (final ArrayList<Integer> arr;) non è un'opzione perché l'array cambia sempre la dimensione o i valori degli elementi.

Se non riuscissi a trovare una soluzione, sto minacciando di tornare al C++ o di rendere tutto pubblico e non dovresti mai ottenere il mio software: D


MODIFICARE:un'altra domanda importante:Sto chiedendo qualcosa che non va bene (per quanto riguarda l'ingegneria del software), voglio dire che se i creatori di JAVA pensavano di non avere riferimenti const (restituendo riferimenti di sola lettura), allora devo chiedere qualcosa che può essere gestito in altro modo.oppure la progettazione del mio programma è sbagliata, sono così confuso.

È stato utile?

Soluzione

Avvolgi il valore restituito con java.util.Collections.unmodifyingList.Non crea una copia dei dati, ma racchiude l'elenco originale e delega le operazioni di sola lettura all'elenco sottostante.Le operazioni che modificherebbero l'elenco vengono rifiutate in fase di esecuzione tramite UnsupportedOperationException.

Tuo

return arrayList;

diventa

return Collections.unmodifiableList(arrayList);

Sfortunatamente i vincoli di sola lettura non verranno applicati dal compilatore.Verranno tuttavia applicati in fase di esecuzione.

Hai a tua disposizione anche: immodificabileSet, immodificabileMap, immodificabileCollection, immodificabileSortedSet, E immodificabileSortedMap.E se ciò non bastasse, puoi comunque trarre ispirazione da questo approccio progettuale generale e creare le tue classi wrapper di sola lettura personalizzate.

Altri suggerimenti

:) Sono disponibili diverse opzioni:

  • Non esporre getter, forniscono solo i metodi che sono autorizzati a chiamata, per es.

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

  • Return oggetto immutabile:

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

Si potrebbe anche usare Google Guava 's immutabile collezioni . In questo caso, si potrebbe memorizzare un ImmutableList nel vostro campo.

Naturalmente, se le vostre esigenze di classe di modificare questa lista internamente, utilizzando ImmutableList potrebbe rivelarsi una cattiva idea, dal momento che è necessario creare una nuova istanza ImmutableList e riassegnare al campo di volta in volta ...

ma è perfetto quando si conosce la lista non cambierà dopo la costruzione dell'oggetto.

esempio Immutable (elenco non cambierà dopo la costruzione oggetto)

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

esempio Mutevole (elenco può essere modificato solo con il 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);
    }
}

Commento

  • Lo so che è spesso consigliato di metodi make restituiscono il tipo più generica possibile (List in questo caso), ma io preferisco dichiarare tipo di ritorno di mio getter come ImmutableList, perché agisce come documentazione (non è necessario il documento del lista restituita immutabilità nel Javadoc) e come un contratto di API. E 'come dire "I garanzia questa lista per essere immutabile, tu non devi preoccuparti o difensiva copiarlo". Ed è molto conciso.
  • ImmutableList.copyOf() è grande, dal momento che rifiuta automaticamente liste nulli (gettando NullPointerException). Respinge inoltre elementi nulli. E non copierà l'elenco di origine se è già un ImmutableList, che evita di un'istanza oggetto inutile.
  • Nel secondo esempio, inizializzare il campo per un ImmutableList vuoto utilizzando ImmutableList.of(), perché è buona norma ritorno collezioni vuoti invece di valori nulli ( Null Object modello ). Si potrebbe pensare che questo crea di istanze oggetto inutile, ma in realtà ImmutableList.of() restituisce un Singleton.

C'è un'alternativa al metodo unmodifiableList. Si può solo restituire una copia di questo array privato. Ad esempio,

    return your_private_array.clone();

Bene, ci potrebbe essere una riduzione delle prestazioni per questo. Ma avete interfaccia invariata (si torna ancora una matrice).

unmodifiableList è sicuramente la risposta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top