2012-03-19 13 views
7

Per fare una classe immutabile, quello che posso fare è:fare una classe immutabili in Java

1) Fai classe finale
2) non forniscono setter
3) contrassegnare tutte le variabili come definitiva

ma se la mia classe ha un altro oggetto di qualche altra classe quindi, somone può cambiare il valore di tale oggetto

class MyClass{ 
final int a; 
final OtherClass other 

MyClass(int a ,OtherClass other){ 
    this.a = a; 
    this.other = other; 
} 

int getA(){ 
    return a; 
} 

OtherClass getOther(){ 
    return other; 
} 

public static void main(String ags[]){ 
    MyClass m = new Myclass(1,new OtherClass); 
    Other o = m.getOther(); 
    o.setSomething(xyz) ; //This is the problem ,How to prevent this? 

} 
} 
+4

non scrivere il metodo impostato –

+0

@LuiggiMendoza, penso che Other/OtherClass è pensato per essere una classe che non controlla. –

+3

Scrivi un wrapper per l'altra classe e crea solo i getter. – Nican

risposta

3

a) effettuare i OtherClass immutabile così

o

B) non consentono l'accesso diretto all'oggetto OtherClass, fornendo invece solo getter per agire come un proxy.

Modifica per aggiungere: Si potrebbe fare una copia completa di OtherClass e restituire una copia anziché l'originale, ma che in genere non è il tipo di comportamento che ci si aspetterebbe in Java.

1

presumo OtherClass (dal modo in cui si dice Altro volta) è destinata ad essere una classe che non controlli o che deve avere un setter.

Se non è possibile rimuovere getOther, modificarlo in getOtherView e restituire una visualizzazione di sola lettura di other. Ci saranno wrapper per tutti i metodi get, ma nessun set.

1

Restituisci cloni profondi dai getter. Potresti scoprire che non è un compito facile.

1

Tutti gli oggetti a cui viene fatto riferimento nella classe immutabile devono essere immutabili, o almeno essere incapsulati come privati ​​e assicurarsi che non siano modificati (non all'interno dei metodi della classe e sicuramente non dall'esterno). Per esempio, se si dispone di questa situazione:

public class MyImmutable { 
    private MutableClass mutableObject; 
} 

... Non è possibile fornire il metodo getMutableObject(), perché così facendo si aprirà la porta per le modifiche al di fuori, come questo:

myImmutable.getMutableObject().setSomeAttribute(newValue); 

Come caso speciale di quanto sopra, tutte le collezioni e/o le mappe devono essere rese immutabili, con i metodi ummodifiableXXX() nella classe Collections.

1

non è possibile (ragionevolmente) fermarlo in Java. se non hai il controllo sull'altra classe, ci sono modi per ottenere in modo efficace un comportamento immutabile, ma può essere molto costoso nella pratica. in pratica, devi sempre restituire una copia di quella classe in qualsiasi valore di ritorno del metodo pubblico. (il jdk ha effettivamente questo problema con la classe TimeZone).

1

Ma se la mia classe ha un altro oggetto di qualche altra classe quindi, somone può cambiare il valore di tale oggetto ...

oggetti Java non sono primitivi. Se si contrassegna una primitiva come finale, il suo valore non può essere modificato una volta assegnato. Tuttavia, i contenuti degli oggetti non possono essere definitivi, solo i riferimenti agli oggetti possono essere definitivi. Quindi non puoi creare un oggetto in questo modo.

Una soluzione potrebbe essere l'abbandono di tutti i metodi setter/mutator che potrebbero modificare i particolari campi dell'oggetto e incapsularli in un modo che è possibile solo accedervi e non modificarli.

2

L'immutabilità è meglio considerata dal punto di vista dell'utente API. Così il vostro API oggetto deve soddisfare le seguenti due condizioni:

  1. c'è modo per un utente esterno per modificare il valore dell'oggetto
  2. Una garanzia che ogni volta che l'utente legge o fa uso del valore dell'oggetto in il futuro, otterrà lo stesso risultato

Nota importante: si è infatti bene avere dati mutabili all'interno di un oggetto immutabile finché si comporta come un oggetto immutabile dal punto di vista dell'utente API. Si consideri ad esempio java.lang.String: sebbene sia generalmente considerata come la classe immutabile definitiva, in effetti ha un campo interno mutabile per la memorizzazione nella cache dell'hashCode (non molte persone lo sanno!).

Quindi, per rispondere alla sua domanda, se si desidera contenere un altro oggetto (mutabile) all'interno di un oggetto immutabile, allora di solito è necessario effettuare una o più delle seguenti operazioni:

  • garanzia che nessun altro può cambiare il valore dell'oggetto mutabile. In genere ciò significa garantire che nessun altro possa avere un riferimento all'oggetto mutabile, quindi questo è solitamente possibile solo se si crea l'oggetto da solo anziché accettare un riferimento dall'esterno.
  • Prendere una copia profonda difensiva dell'oggetto mutabile e non distribuire i riferimenti alla nuova copia. Consenti solo le operazioni che leggono la nuova copia nell'API pubblica. Se è necessario fornire un riferimento a questo oggetto, è necessario prendere un'altra copia difensiva (per evitare di fornire un riferimento alla copia interna).
  • Utilizzare un wrapper immutabile per l'oggetto mutabile. Qualcosa come Collections.unmodifiableList. Ciò è utile se si desidera distribuire un riferimento all'oggetto interno mutabile ma non si vuole correre il rischio che venga modificato.

Tutte queste soluzioni sono un po 'hacky - una soluzione migliore nel complesso è evitare l'uso di oggetti mutabili all'interno di oggetti immutabili. A lungo termine si tratta di problemi, perché prima o poi si verificherà un riferimento mutabile e si avrà un bug estremamente difficile da trovare. Sei meglio muovendo verso una gerarchia piena di oggetti immutabili (l'approccio adottato dalle lingue come Scala e Clojure)

+0

Quasi tutti gli oggetti che contengono una raccolta di dimensioni variabili avranno una matrice come backing store, quindi evitare completamente gli oggetti mutabili annidati non è generalmente pratico (tutto ciò che può essere fatto con un array può essere fatto usando alberi immutabili, ma in molti casi gli array saranno più di un ordine di grandezza più veloce). – supercat

1

E 'possibile creare la classe immutabili in Java da modi seguenti

1.Do non Fornire setter metodi.

2. Fare clic su Tutti i campi sono definitivi e privati.

3.Make Class come finale.

+0

valido solo quando i campi sono immutabili. – KillBill

Problemi correlati