Risposte:
La transient
parola chiave in Java viene utilizzata per indicare che un campo non dovrebbe far parte del processo di serializzazione (che significa salvato, come in un file).
Da Java Language Specification, Java SE 7 Edition , Sezione 8.3.1.3. transient
Campi :
Le variabili possono essere contrassegnate
transient
per indicare che non fanno parte dello stato persistente di un oggetto.
Ad esempio, potresti avere campi derivati da altri campi e dovrebbero essere eseguiti solo a livello di programmazione, anziché mantenere lo stato tramite la serializzazione.
Ecco una GalleryImage
classe che contiene un'immagine e una miniatura derivata dall'immagine:
class GalleryImage implements Serializable
{
private Image image;
private transient Image thumbnailImage;
private void generateThumbnail()
{
// Generate thumbnail.
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
generateThumbnail();
}
}
In questo esempio, thumbnailImage
è un'immagine in miniatura generata richiamando il generateThumbnail
metodo.
Il thumbnailImage
campo è contrassegnato come transient
, quindi solo l'originale image
è serializzato piuttosto che persistere sia l'immagine originale che l'immagine di anteprima. Ciò significa che sarebbe necessario meno spazio di archiviazione per salvare l'oggetto serializzato. (Naturalmente, questo può o non può essere desiderabile a seconda dei requisiti del sistema - questo è solo un esempio.)
Al momento della deserializzazione, readObject
viene chiamato il metodo per eseguire tutte le operazioni necessarie per ripristinare lo stato dell'oggetto allo stato in cui si è verificata la serializzazione. Qui, la miniatura deve essere generata, quindi il readObject
metodo viene sovrascritto in modo che la miniatura venga generata chiamando il generateThumbnail
metodo.
Per ulteriori informazioni, l'articolo Scopri i segreti dell'articolo API di serializzazione Java (che era originariamente disponibile su Sun Developer Network) ha una sezione che discute l'uso e presenta uno scenario in cui la transient
parola chiave viene utilizzata per impedire la serializzazione di determinati campi.
Prima di comprendere la transient
parola chiave, è necessario comprendere il concetto di serializzazione. Se il lettore è a conoscenza della serializzazione, saltare il primo punto.
La serializzazione è il processo per rendere persistente lo stato dell'oggetto. Ciò significa che lo stato dell'oggetto viene convertito in un flusso di byte da utilizzare per persistere (ad es. Memorizzazione di byte in un file) o trasferimento (ad es. Invio di byte attraverso una rete). Allo stesso modo, possiamo usare la deserializzazione per riportare lo stato dell'oggetto dai byte. Questo è uno dei concetti importanti nella programmazione Java poiché la serializzazione viene utilizzata principalmente nella programmazione in rete. Gli oggetti che devono essere trasmessi attraverso la rete devono essere convertiti in byte. A tale scopo, ogni classe o interfaccia deve implementare l' Serializable
interfaccia. È un'interfaccia marcatore senza alcun metodo.
transient
parola chiave e il suo scopo?Per impostazione predefinita, tutte le variabili dell'oggetto vengono convertite in uno stato persistente. In alcuni casi, potresti voler evitare il persistere di alcune variabili perché non hai la necessità di persistere quelle variabili. Quindi puoi dichiarare quelle variabili come transient
. Se la variabile viene dichiarata come transient
, non sarà persistente. Questo è lo scopo principale della transient
parola chiave.
Voglio spiegare i due punti precedenti con il seguente esempio:
package javabeat.samples;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class NameStore implements Serializable{
private String firstName;
private transient String middleName;
private String lastName;
public NameStore (String fName, String mName, String lName){
this.firstName = fName;
this.middleName = mName;
this.lastName = lName;
}
public String toString(){
StringBuffer sb = new StringBuffer(40);
sb.append("First Name : ");
sb.append(this.firstName);
sb.append("Middle Name : ");
sb.append(this.middleName);
sb.append("Last Name : ");
sb.append(this.lastName);
return sb.toString();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
// writing to object
o.writeObject(nameStore);
o.close();
// reading from object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
NameStore nameStore1 = (NameStore)in.readObject();
System.out.println(nameStore1);
}
}
E l'output sarà il seguente:
First Name : Steve
Middle Name : null
Last Name : Jobs
Il secondo nome è dichiarato come transient
, quindi non verrà archiviato nella memoria permanente.
NameFormatter
usato per guidare toString()
. O qualsiasi altra cosa relativa alla configurazione, alla visualizzazione o alla logica aziendale, ... al contrario dei dati.
Per consentire di definire variabili che non si desidera serializzare.
In un oggetto potresti avere informazioni che non vuoi serializzare / persistere (forse un riferimento a un oggetto factory padre), o forse non ha senso serializzare. Contrassegnandoli come "transitori" significa che il meccanismo di serializzazione ignorerà questi campi.
Il mio piccolo contributo:
Che cos'è un campo transitorio?
Fondamentalmente, qualsiasi campo modificato con la transient
parola chiave è un campo temporaneo.
Perché sono necessari campi transitori in Java?
La transient
parola chiave offre un certo controllo sul processo di serializzazione e consente di escludere alcune proprietà degli oggetti da questo processo. Il processo di serializzazione viene utilizzato per rendere persistenti gli oggetti Java, principalmente in modo che i loro stati possano essere conservati mentre vengono trasferiti o inattivi. A volte, ha senso non serializzare determinati attributi di un oggetto.
Quali campi dovresti contrassegnare come transitori?
Ora conosciamo lo scopo ditransient
campi di parole chiave e transitori, è importante sapere quali campi contrassegnare i transitori. Neanche i campi statici sono serializzati, quindi anche la parola chiave corrispondente farebbe il trucco. Ma questo potrebbe rovinare il tuo design di classe; è qui che la transient
parola chiave viene in soccorso. Cerco di non consentire la serializzazione dei campi i cui valori possono essere derivati da altri, quindi li contrassegno come transitori. Se si dispone di un campo chiamato il interest
cui valore può essere calcolato da altri campi ( principal
, rate
& time
), non è necessario serializzarlo.
Un altro buon esempio è con il conteggio delle parole degli articoli. Se stai salvando un intero articolo, non c'è davvero bisogno di salvare il conteggio delle parole, perché può essere calcolato quando l'articolo viene "deserializzato". O pensa ai logger;Logger
le istanze non devono quasi mai essere serializzate, quindi possono essere rese transitorie.
transient
transient
Una transient
variabile è una variabile che potrebbe non essere serializzata.
Un esempio di quando questo potrebbe essere utile che viene in mente è, le variabili che hanno senso solo nel contesto di una specifica istanza di oggetto e che diventano non valide dopo aver serializzato e deserializzato l'oggetto. In tal caso è utile che tali variabili diventino null
invece in modo da poterle reinizializzare con dati utili quando necessario.
transient
viene utilizzato per indicare che non è necessario serializzare un campo di classe. Probabilmente il miglior esempio è un Thread
campo. Di solito non c'è motivo di serializzare a Thread
, poiché il suo stato è molto "specifico del flusso".
A
riferimento a una classe non serializzabile B
(come Thread
nell'esempio), allora A
deve contrassegnare il riferimento come transient
XOR deve sovrascrivere il processo di serializzazione predefinito per fare qualcosa di ragionevole con B
XOR supporre che solo le sottoclassi serializzabili di B
siano effettivamente referenziate (quindi la sottoclasse effettiva deve occuparsi del genitore "cattivo" B
) XOR accetta che la serializzazione fallirà. In un solo caso (contrassegnato come transitorio) B
viene automaticamente e silenziosamente ignorato.
Anche i sistemi di serializzazione diversi da quelli nativi Java possono utilizzare questo modificatore. L'ibernazione, ad esempio, non persisterà nei campi contrassegnati con @Transient o con il modificatore transitorio . Anche la terracotta rispetta questo modificatore.
Credo che il significato figurativo del modificatore sia "questo campo è solo per uso in memoria. Non persistere o spostarlo al di fuori di questa particolare VM in alcun modo. È non portatile". cioè non puoi fare affidamento sul suo valore in un altro spazio di memoria della VM. Proprio come volatile significa che non puoi fare affidamento su una certa semantica di memoria e thread.
transient
non sarebbe una parola chiave se fosse stata progettata in questo momento. Probabilmente avrebbero usato un'annotazione.
Perché non tutte le variabili sono di natura serializzabile
Prima di rispondere a questa domanda, devo spiegarti la SERIALIZZAZIONE , perché se capisci cosa significa serializzazione nel computer scientifico puoi facilmente capire questa parola chiave.
Serializzazione
Quando un oggetto viene trasferito attraverso la rete / salvato su supporto fisico (file, ...), l'oggetto deve essere "serializzato". La serializzazione converte le serie di oggetti di stato byte. Questi byte vengono inviati sulla rete / salvati e l'oggetto viene ricreato da questi byte.
Esempio
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Ora, se si vuole fare NON TRANSFERT / SALVATO campo di questo oggetto SO , è possibile utilizzare parole chiave transient
private transient attr2;
È necessario quando non si desidera condividere alcuni dati sensibili associati alla serializzazione.
Thread
(credito ad @AH per esempio), nel qual caso lo contrassegneresti come transitorio. Tuttavia, un thread non è di per sé un dato sensibile, non ha senso logicamente serializzarlo (e non è serializzabile).
Secondo il significato transitorio di Google == che dura solo per un breve periodo; impermanente.
Ora se vuoi rendere qualsiasi cosa transitoria in java usa una parola chiave transitoria.
Q: dove usare i transitori?
A: Generalmente in Java possiamo salvare i dati in file acquisendoli in variabili e scrivendo quelle variabili in file, questo processo è noto come Serializzazione. Ora, se vogliamo evitare che i dati variabili vengano scritti su file, renderemo tale variabile come transitoria.
transient int result=10;
Nota: le variabili transitorie non possono essere locali.
In parole semplici, la parola chiave java transitoria protegge i campi da Serialize come parti di contro campi non transitori.
In questo frammento di codice la nostra classe astratta BaseJob implementa l'interfaccia serializzabile, si estende da BaseJob ma non è necessario serializzare le origini dati remote e locali; serializzare solo i campi OrganizationName e isSynced.
public abstract class BaseJob implements Serializable{
public void ShouldRetryRun(){}
}
public class SyncOrganizationJob extends BaseJob {
public String organizationName;
public Boolean isSynced
@Inject transient RemoteDataSource remoteDataSource;
@Inject transient LocalDaoSource localDataSource;
public SyncOrganizationJob(String organizationName) {
super(new
Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());
this.organizationName = organizationName;
this.isSynced=isSynced;
}
}
Codice di esempio semplificato per parola chiave temporanea.
import java.io.*;
class NameStore implements Serializable {
private String firstName, lastName;
private transient String fullName;
public NameStore (String fName, String lName){
this.firstName = fName;
this.lastName = lName;
buildFullName();
}
private void buildFullName() {
// assume building fullName is compuational/memory intensive!
this.fullName = this.firstName + " " + this.lastName;
}
public String toString(){
return "First Name : " + this.firstName
+ "\nLast Name : " + this.lastName
+ "\nFull Name : " + this.fullName;
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
buildFullName();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
o.writeObject(new NameStore("Steve", "Jobs"));
o.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
NameStore ns = (NameStore)in.readObject();
System.out.println(ns);
}
}
Un campo che viene dichiarato con modificatore transitorio non prenderà parte al processo serializzato. Quando un oggetto viene serializzato (salvato in qualsiasi stato), i valori dei suoi campi transitori vengono ignorati nella rappresentazione seriale, mentre il campo diverso dai campi transitori prenderà parte al processo di serializzazione. Questo è lo scopo principale della parola chiave transitoria.
@DoNotSerialize
?