2011-08-16 18 views
60

È consigliabile non esporre i riferimenti interni di un oggetto (entità). Quindi, se un oggetto ha un campo di tipo java.util.Date, ad esempio il getter per questo campo deve restituire non la data originale ma una copia di esso.java.util.Date clone o copia per non esporre riferimento interno

Ma per un java.util.Date ci sono due modi comuni per creare la copia:

  • clone: ​​(Date) originalDate.clone()
  • copia via costruttore new Date(originalDate.getTime())

La mia domanda è, che il modo è migliore, e perché?

risposta

40

Se è sicuramente solo uno Date, non farà alcuna differenza in entrambi i casi.

Se l'oggetto effettivo potrebbe essere una sottoclasse di Date (come java.sql.Date) poi mi auguro che clone() sarebbe conservare le informazioni extra (tra cui la classe è), mentre chiamando il costruttore no.

Per inciso, se hai usato Joda Time non avresti questo problema, perché ci sono un sacco di tipi immutabili da usare. È anche un'API molto migliore :)

+6

A partire da Java 8 l'API java.time può essere utilizzata al posto di Joda Time. – Akash

33

Leggi Effective Java. Il modo migliore per creare copie è utilizzare l'approccio del costruttore di copie.

Bill Venners: nel tuo libro si consiglia di utilizzare un costruttore di copia anziché implementare Clonazione e clonazione. Potresti compilare lo ?

Josh Bloch: Se hai letto l'articolo sulla clonazione nel mio libro, specialmente se leggi tra le righe, saprai che penso che il clone sia profondamente danneggiato. Ci sono alcuni difetti di progettazione, il più grande di che è che l'interfaccia Cloneable non ha un metodo clone. E questo significa che semplicemente non funziona: fare qualcosa Cloneable non dice nulla su cosa puoi fare con esso. Invece, dice qualcosa su ciò che può fare internamente. Si dice che chiamando ripetutamente il Super.clone finisce per chiamare il metodo clone dell'oggetto, questo metodo restituirà una copia campo dell'originale nel metodo .

+5

Questo è il modo migliore per progettare la clonazione nelle proprie classi, sebbene richieda al chiamante di * sapere * quale sottoclasse concreta viene utilizzata o meno * cura * quale sottoclasse concreta viene utilizzata. Vedi la mia risposta per un esempio di come può fare la differenza. –

14

Se si sta codificando in modo difensivo, si vorrà il costruttore di copie. Vedi this passage from Effective Java:

Si noti inoltre che non è stato utilizzato il metodo di clonazione di Date per effettuare le copie difensive. Poiché Date non è definitivo, il metodo clone non è garantito per restituire un oggetto la cui classe è java.util.Date; potrebbe restituire un'istanza di una sottoclasse non sicura appositamente progettata per maliziosi malintenzionati. Tale sottoclasse potrebbe, ad esempio, registrare un riferimento a ciascuna istanza in un elenco statico privato al momento della sua creazione e consentire all'utente malintenzionato di accedere a questo elenco. Ciò darebbe all'aggressore un regno libero su tutte le istanze. Per evitare questo tipo di attacco, non utilizzare il metodo clone per creare una copia difensiva di un parametro il cui tipo è sottoclassato da parti non attendibili.

Problemi correlati