Storia della questione:
Java ha supportato fin dall'inizio il meccanismo di serializzazione degli oggetti tramite l'interfaccia Serializable. A volte è necessario salvare lo stato di un oggetto, ma non tutti i campi dovrebbero essere serializzati: ad esempio, potrebbero essere sensibili alla sicurezza o calcolati dinamicamente. Per questi casi è stato inventato il modificatore transient.
Problema:
Se si serializza un oggetto interamente, senza considerare le peculiarità dei singoli campi, si può incorrere in perdite di dati privati o non idonei alla serializzazione. Inoltre, la serializzazione e la deserializzazione di campi pesanti o temporanei (come flussi, connessioni a database) può portare a errori o a un calo delle prestazioni.
Soluzione:
Utilizza il modificatore transient per i campi che non devono essere serializzati al momento del salvataggio dell'oggetto. Questi campi vengono semplicemente ignorati dal meccanismo di serializzazione e, durante la deserializzazione, assumono valori predefiniti (ad esempio, null per i tipi di riferimento o 0 per i numeri).
Esempio di codice:
import java.io.*; class User implements Serializable { private String username; private transient String password; // Non serializzato! public User(String username, String password) { this.username = username; this.password = password; } }
Caratteristiche chiave:
Può un campo statico essere transient?
Risposta: È possibile dichiarare un campo come static transient, ma non ha senso: i campi statici non vengono serializzati poiché appartengono alla classe e non all'oggetto.
È possibile avere un controllo completo sulla serializzazione dei campi transient?
Risposta: Sì, implementando i metodi private void writeObject(ObjectOutputStream out) e private void readObject(ObjectInputStream in), è possibile serializzare manualmente anche i campi transient se necessario.
Esempio di codice:
private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); // out.writeObject(password); // se necessario serializzare esplicitamente un campo transient }
Cosa succede a un campo final transient dopo la deserializzazione?
Risposta: i campi final transient ricevono anche valori predefiniti (di solito zero o null), ma poi non possono essere modificati senza particolari stratagemmi, il che porta spesso a bug.
Abbiamo serializzato un oggetto con il campo transient DatabaseConnection. Dopo la deserializzazione abbiamo provato a chiamare metodi su questa connessione — abbiamo ottenuto NullPointerException.
Vantaggi:
Svantaggi:
Abbiamo serializzato un oggetto User con una password transient, durante la deserializzazione nel readObject abbiamo richiesto la password all'utente o ripristinato la connessione.
Vantaggi:
Svantaggi: