Antworten:
Das transient
Schlüsselwort in Java wird verwendet, um anzugeben, dass ein Feld nicht Teil des Serialisierungsprozesses sein soll (dh wie in einer Datei gespeichert).
Aus der Java-Sprachspezifikation, Java SE 7 Edition , Abschnitt 8.3.1.3. transient
Felder :
Variablen können markiert werden,
transient
um anzuzeigen, dass sie nicht Teil des dauerhaften Zustands eines Objekts sind.
Beispielsweise können Felder vorhanden sein, die von anderen Feldern abgeleitet sind und nur programmgesteuert ausgeführt werden sollten, anstatt den Status über die Serialisierung beizubehalten.
Hier ist eine GalleryImage
Klasse, die ein Bild und eine Miniaturansicht enthält, die vom Bild abgeleitet sind:
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 diesem Beispiel thumbnailImage
handelt es sich um ein Miniaturbild, das durch Aufrufen der generateThumbnail
Methode generiert wird .
Das thumbnailImage
Feld ist als markiert transient
, sodass nur das Original image
serialisiert wird, anstatt sowohl das Originalbild als auch das Miniaturbild beizubehalten. Dies bedeutet, dass weniger Speicher benötigt wird, um das serialisierte Objekt zu speichern. (Natürlich kann dies abhängig von den Anforderungen des Systems wünschenswert sein oder auch nicht - dies ist nur ein Beispiel.)
Zum Zeitpunkt der Deserialisierung wird die readObject
Methode aufgerufen, um alle Operationen auszuführen, die erforderlich sind, um den Status des Objekts auf den Status zurückzusetzen, in dem die Serialisierung stattgefunden hat. Hier muss die Miniaturansicht generiert werden, damit die readObject
Methode überschrieben wird, damit die Miniaturansicht durch Aufrufen der generateThumbnail
Methode generiert wird .
Weitere Informationen finden Sie im Artikel Entdecken Sie die Geheimnisse des Java Serialization API- Artikels (der ursprünglich im Sun Developer Network verfügbar war). In diesem Abschnitt wird die Verwendung erläutert und ein Szenario vorgestellt, in dem das transient
Schlüsselwort verwendet wird, um die Serialisierung bestimmter Felder zu verhindern.
Bevor man das transient
Schlüsselwort versteht, muss man das Konzept der Serialisierung verstehen. Wenn der Leser etwas über Serialisierung weiß, überspringen Sie bitte den ersten Punkt.
Bei der Serialisierung wird der Status des Objekts dauerhaft festgelegt. Dies bedeutet, dass der Status des Objekts in einen Bytestrom konvertiert wird, der zum Fortbestehen (z. B. Speichern von Bytes in einer Datei) oder zum Übertragen (z. B. Senden von Bytes über ein Netzwerk) verwendet werden soll. Auf die gleiche Weise können wir die Deserialisierung verwenden, um den Status des Objekts aus Bytes wiederherzustellen. Dies ist eines der wichtigsten Konzepte in der Java-Programmierung, da die Serialisierung hauptsächlich in der Netzwerkprogrammierung verwendet wird. Die Objekte, die über das Netzwerk übertragen werden müssen, müssen in Bytes konvertiert werden. Zu diesem Zweck muss jede Klasse oder Schnittstelle die Serializable
Schnittstelle implementieren . Es ist eine Markierungsschnittstelle ohne Methoden.
transient
Schlüsselwort und sein Zweck?Standardmäßig werden alle Variablen des Objekts in einen dauerhaften Zustand konvertiert. In einigen Fällen möchten Sie möglicherweise vermeiden, dass einige Variablen beibehalten werden, da Sie diese Variablen nicht beibehalten müssen. Sie können diese Variablen also als deklarieren transient
. Wenn die Variable als deklariert ist transient
, wird sie nicht beibehalten. Das ist der Hauptzweck des transient
Schlüsselworts.
Ich möchte die beiden oben genannten Punkte anhand des folgenden Beispiels erläutern:
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);
}
}
Und die Ausgabe wird die folgende sein:
First Name : Steve
Middle Name : null
Last Name : Jobs
Der zweite Vorname wird als deklariert transient
, sodass er nicht im dauerhaften Speicher gespeichert wird.
NameFormatter
gebrauchtes zum Fahren haben toString()
. Oder irgendetwas anderes, das sich auf Konfiguration, Anzeige oder Geschäftslogik bezieht, im Gegensatz zu Daten.
Damit können Sie Variablen definieren, die Sie nicht serialisieren möchten.
In einem Objekt befinden sich möglicherweise Informationen, die Sie nicht serialisieren / beibehalten möchten (möglicherweise ein Verweis auf ein übergeordnetes Factory-Objekt), oder die Serialisierung ist möglicherweise nicht sinnvoll. Wenn Sie diese als "vorübergehend" markieren, ignoriert der Serialisierungsmechanismus diese Felder.
Mein kleiner Beitrag:
Was ist ein Übergangsfeld?
Grundsätzlich ist jedes mit dem transient
Schlüsselwort geänderte Feld ein Übergangsfeld.
Warum werden in Java Übergangsfelder benötigt?
Mit dem transient
Schlüsselwort können Sie den Serialisierungsprozess steuern und einige Objekteigenschaften von diesem Prozess ausschließen. Der Serialisierungsprozess wird verwendet, um Java-Objekte beizubehalten, hauptsächlich, damit ihre Zustände beibehalten werden können, während sie übertragen oder inaktiv sind. Manchmal ist es sinnvoll, bestimmte Attribute eines Objekts nicht zu serialisieren.
Welche Felder sollten Sie als vorübergehend markieren?
Jetzt kennen wir den Zweck destransient
Bei Schlüsselwort- und Übergangsfeldern ist es wichtig zu wissen, welche Felder vorübergehend markiert werden sollen. Statische Felder werden ebenfalls nicht serialisiert, daher würde auch das entsprechende Schlüsselwort ausreichen. Aber dies könnte Ihr Klassendesign ruinieren. Hier kommt das transient
Schlüsselwort zur Rettung. Ich versuche, die Serialisierung von Feldern, deren Werte von anderen abgeleitet werden können, nicht zuzulassen, daher markiere ich sie als vorübergehend. Wenn Sie ein Feld mit dem Namen haben, interest
dessen Wert aus anderen Feldern ( principal
, rate
& time
) berechnet werden kann , muss es nicht serialisiert werden.
Ein weiteres gutes Beispiel ist die Anzahl der Artikelwörter. Wenn Sie einen ganzen Artikel speichern, müssen Sie die Wortanzahl nicht speichern, da sie berechnet werden kann, wenn der Artikel "deserialisiert" wird. Oder denken Sie an Holzfäller;Logger
Instanzen müssen fast nie serialisiert werden, damit sie vorübergehend gemacht werden können.
transient
transient
Eine transient
Variable ist eine Variable, die möglicherweise nicht serialisiert wird.
Ein Beispiel dafür, wann dies nützlich sein könnte, sind Variablen, die nur im Kontext einer bestimmten Objektinstanz sinnvoll sind und die ungültig werden, sobald Sie das Objekt serialisiert und deserialisiert haben. In diesem Fall ist es hilfreich, diese Variablen null
stattdessen zu verwenden, damit Sie sie bei Bedarf mit nützlichen Daten neu initialisieren können.
transient
wird verwendet, um anzuzeigen, dass ein Klassenfeld nicht serialisiert werden muss. Das wahrscheinlich beste Beispiel ist ein Thread
Feld. Es gibt normalerweise keinen Grund, a zu serialisieren Thread
, da sein Status sehr "flussspezifisch" ist.
A
auf eine nicht serialisierbare Klasse verweist B
(wie Thread
in Ihrem Beispiel), A
muss entweder die Referenz markiert werden, da transient
XOR den Standard-Serialisierungsprozess überschreiben muss, um mit B
XOR etwas Vernünftiges zu tun, vorausgesetzt, dass nur serialisierbare Unterklassen von B
tatsächlich referenziert werden (Die eigentliche Unterklasse muss sich also um ihre "schlechten" Eltern kümmern. B
) XOR akzeptiert, dass die Serialisierung fehlschlägt. In nur einem Fall (als vorübergehend markiert) B
wird automatisch und stillschweigend übersprungen.
Andere Serialisierungssysteme als das native Java können ebenfalls diesen Modifikator verwenden. Im Ruhezustand bleiben beispielsweise keine Felder erhalten, die mit @Transient oder dem Transientenmodifikator markiert sind . Auch Terrakotta respektiert diesen Modifikator.
Ich glaube, die bildliche Bedeutung des Modifikators lautet: "Dieses Feld ist nur für den speicherinternen Gebrauch bestimmt. Behalten Sie es nicht bei oder verschieben Sie es in irgendeiner Weise außerhalb dieser bestimmten VM. Es ist nicht portierbar." Das heißt, Sie können sich nicht auf den Wert in einem anderen VM-Speicher verlassen. Ähnlich wie bei flüchtig bedeutet, dass Sie sich nicht auf bestimmte Speicher- und Thread-Semantiken verlassen können.
transient
wäre kein Schlüsselwort, wenn es zu diesem Zeitpunkt entworfen würde. Sie würden wahrscheinlich eine Anmerkung verwenden.
Weil nicht alle Variablen serialisierbar sind
Bevor ich auf diese Frage antworte, muss ich Ihnen die SERIALISIERUNG erklären , denn wenn Sie verstehen, was Serialisierung in Wissenschaftscomputern bedeutet, können Sie dieses Schlüsselwort leicht verstehen.
Serialisierung
Wenn ein Objekt über das Netzwerk übertragen / auf einem physischen Medium (Datei, ...) gespeichert wird, muss das Objekt "serialisiert" werden. Die Serialisierung konvertiert Byte-Status-Objektreihen. Diese Bytes werden im Netzwerk gesendet / gespeichert und das Objekt wird aus diesen Bytes neu erstellt.
Beispiel
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Wenn Sie nun das Feld NICHT ÜBERTRAGEN / GESPEICHERT dieses Objekts SO möchten , können Sie das Schlüsselwort verwenden transient
private transient attr2;
Dies ist erforderlich, wenn Sie keine vertraulichen Daten für die Serialisierung freigeben möchten.
Thread
(z. B. eine Gutschrift für @AH). In diesem Fall würden Sie es als vorübergehend markieren. Ein Thread ist jedoch an und für sich kein vertrauliches Datenelement. Es macht einfach keinen logischen Sinn, es zu serialisieren (und es ist nicht serialisierbar).
Laut Google Transient bedeutet == nur für kurze Zeit; unbeständig.
Wenn Sie nun in Java etwas vorübergehend machen möchten, verwenden Sie das Schlüsselwort transient.
F: Wo kann man Transient verwenden?
A: Im Allgemeinen können wir in Java Daten in Dateien speichern, indem wir sie in Variablen erfassen und diese Variablen in Dateien schreiben. Dieser Vorgang wird als Serialisierung bezeichnet. Wenn wir nun vermeiden möchten, dass Variablendaten in eine Datei geschrieben werden, würden wir diese Variable als vorübergehend festlegen.
transient int result=10;
Hinweis: Transiente Variablen können nicht lokal sein.
Einfach ausgedrückt, schützt das vorübergehende Java-Schlüsselwort Felder vor dem Serialisieren als nicht vorübergehende Felder.
In diesem Codefragment unserer abstrakten Klasse BaseJob implementieren Sie die serialisierbare Schnittstelle. Wir erweitern sie von BaseJob, müssen jedoch die entfernten und lokalen Datenquellen nicht serialisieren. Serialisieren Sie nur die Felder organisationName und 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;
}
}
Vereinfachter Beispielcode für das Schlüsselwort transient.
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);
}
}
Ein Feld, das mit einem Transientenmodifikator deklariert wird, nimmt nicht am serialisierten Prozess teil. Wenn ein Objekt serialisiert wird (in einem beliebigen Status gespeichert), werden die Werte seiner Übergangsfelder in der seriellen Darstellung ignoriert, während andere Felder als Übergangsfelder am Serialisierungsprozess teilnehmen. Dies ist der Hauptzweck des vorübergehenden Schlüsselworts.
@DoNotSerialize
?