2012-05-10 12 views
16

Se un riferimento a un oggetto viene passato a un metodo, è possibile rendere l'oggetto "Sola lettura" al metodo?È possibile rendere un oggetto "Sola lettura" a un metodo

+5

c'è una vecchia, ma comunque buona risorsa: http://www.cs.uwm.edu/~boyland/papers/readonly-talk.pdf –

+0

che dire di memorizzare un riferimento all'oggetto, clonarlo e confrontare di volta in volta se nulla è cambiato? –

risposta

15

In senso stretto. Cioè, un riferimento che può mutare un oggetto non può essere trasformato in un riferimento che non può mutare un oggetto. Inoltre, non c'è modo di esprimere che un tipo è immutabile o mutevole, a parte l'uso delle convenzioni.

L'unica caratteristica che garantisce una qualche forma di immutabilità sarebbe i campi final - una volta scritti non possono essere modificati.

Detto questo, ci sono modi per progettare le classi in modo tale che la mutazione indesiderata sia impedita. Qui ci sono alcune tecniche:

  • Defensive Copying. Passa una copia dell'oggetto, in modo che se è mutato non infrange gli invarianti interni.

  • Usa modificatori di accesso e/o interfaccia di esporre solo i metodi di sola lettura. È possibile utilizzare i modificatori di accesso (public/private/protected), eventualmente combinati con l'interfaccia, in modo che solo alcuni metodi siano visibili all'altro oggetto. Se i metodi esposti sono di sola lettura per natura, sei al sicuro.

  • Fai il tuo oggetto immutabile di default. Qualsiasi operazione sull'oggetto restituisce effettivamente una copia dell'oggetto.

Inoltre, si noti che l'API in SDK hanno talvolta metodi che restituiscono una versione immutabile di un oggetto, ad esempio Collections.unmodifiableList. Un tentativo di mutare una lista immutabile genererà un'eccezione. Questo non impone staticamente l'immutabilità (in fase di compilazione con il sistema di tipo statico), ma è un modo economico ed efficace per rafforzarlo dinamicamente (in fase di esecuzione).

Ci sono state molte proposte di ricerca dell'estensione Java per controllare meglio l'aliasing e l'accessibilità.Ad esempio, aggiunta di una parola chiave readonly. Nessuno di loro è per quanto ne so pianificato per l'inclusione nella versione futura di Java. Si può avere uno sguardo a questi puntatori se siete interessati:

Il quadro di controllo è molto interessante. Nel quadro dei correttori, esaminare il correttore dei tipi di universo generico, il controllo di immutabilità IGJ e il controllo dell'immutabilità di Javari. Il framework funziona usando le annotazioni, quindi non è invadente.

+0

Il pdf di sola lettura soffre del link rot. – flup

3

No. Tuttavia, è possibile provare a clonare l'oggetto prima di passarlo, quindi eventuali modifiche apportate dal metodo non influiranno sull'oggetto originale.

6

No, non senza decorazione, il compositing, la clonazione, ecc

6

Non c'è alcun meccanismo generale per questo. Avrai bisogno di scrivere codice di caso speciale per ottenerlo, come scrivere un wrapper immutabile (vedi Collections.unmodifiableList).

1

È possibile definire tutti i parametri degli oggetti come final ma questo rende l'oggetto di lettura solo per tutti.

3

Si potrebbe realizzare una cosa simile nella maggior parte dei casi clonando il Object come la prima istruzione del metodo, come questo ...

public void readOnlyMethod(Object test){ 
    test = test.clone(); 
    // other code here 
} 

Quindi, se hai chiamato readOnlyMethod() e passare in qualsiasi Object, un verrà preso il clone di Object. Il clone utilizza lo stesso nome del parametro del metodo, quindi non c'è il rischio di cambiare accidentalmente l'originale Object.

+1

Ciò richiede che l'oggetto realizzi correttamente 'clone' e, poiché questa è un'API f * ed-up, le classi moderne raramente si occupano di esso. –

+0

corretto. Tuttavia, mi auguro che la maggior parte delle classi Java core implementino correttamente 'clone(), quindi questo coprirà * la maggior parte * delle situazioni. Probabilmente è il più vicino possibile per ottenere un parametro di sola lettura – wattostudios

+1

Che ne dite di 'Collections.unmodifiableList' - che proviene dall'API principale (nessuna clonazione). –

0

A seconda di dove si desidera applicare la regola. Se stai lavorando in modo collaborativo a un progetto, usa final con un commento che indica alla persona successiva che non intendono modificare questo valore. Altrimenti non scrivere semplicemente il metodo a non toccare l'oggetto?

public static void main(String[] args) { 
    cantTouchThis("Cant touch this"); 
} 

/** 
* 
* @param value - break it down 
*/ 
public static void cantTouchThis(final String value) { 
    System.out.println("Value: " + value); 
    value = "Nah nah nah nah"; //Compile time error 
} 

Quindi specificamente a questo metodo, il valore non sarà mai scritta per, e viene applicata al momento della compilazione rendendo la soluzione estremamente robusta. Al di fuori dello scopo di questo metodo, l'oggetto rimane inalterato senza dover creare alcun tipo di wrapper.

0
private boolean isExecuteWriteQueue = false; 
public boolean isWriting(){ 
    final boolean b = isExecuteWriteQueue; 
    return b; 
} 
1

rendendolo implementare un'interfaccia che ha letto solo soltanto i metodi (non setter) questo dà una copia di un oggetto (strada sola copia) e restituendo l'unico esempio lettura di interfaccia invece di restituire l'istanza di un oggetto in sé

Problemi correlati