Antworten:
Das transientSchlü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. transientFelder :
Variablen können markiert werden,
transientum 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 GalleryImageKlasse, 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 thumbnailImagehandelt es sich um ein Miniaturbild, das durch Aufrufen der generateThumbnailMethode generiert wird .
Das thumbnailImageFeld ist als markiert transient, sodass nur das Original imageserialisiert 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 readObjectMethode 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 readObjectMethode überschrieben wird, damit die Miniaturansicht durch Aufrufen der generateThumbnailMethode 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 transientSchlüsselwort verwendet wird, um die Serialisierung bestimmter Felder zu verhindern.
Bevor man das transientSchlü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 SerializableSchnittstelle implementieren . Es ist eine Markierungsschnittstelle ohne Methoden.
transientSchlü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 transientSchlü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.
NameFormattergebrauchtes 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 transientSchlüsselwort geänderte Feld ein Übergangsfeld.
Warum werden in Java Übergangsfelder benötigt?
Mit dem transientSchlü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 destransientBei 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 transientSchlü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, interestdessen 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 transientVariable 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 nullstattdessen zu verwenden, damit Sie sie bei Bedarf mit nützlichen Daten neu initialisieren können.
transientwird verwendet, um anzuzeigen, dass ein Klassenfeld nicht serialisiert werden muss. Das wahrscheinlich beste Beispiel ist ein ThreadFeld. Es gibt normalerweise keinen Grund, a zu serialisieren Thread, da sein Status sehr "flussspezifisch" ist.
Aauf eine nicht serialisierbare Klasse verweist B(wie Threadin Ihrem Beispiel), Amuss entweder die Referenz markiert werden, da transientXOR den Standard-Serialisierungsprozess überschreiben muss, um mit BXOR etwas Vernünftiges zu tun, vorausgesetzt, dass nur serialisierbare Unterklassen von Btatsä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) Bwird 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.
transientwä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?