web-dev-qa-db-de.com

Warum hat Java transiente Felder?

Warum hat Java Transient Felder?

1288
Animesh

Das transient-Schlüsselwort in Java wird verwendet, um anzugeben, dass ein Feld nicht Teil des Serialisierungsprozesses sein darf (was bedeutet, dass es in einer Datei like ist).

Aus der Java-Sprachspezifikation, Java SE 7 Edition , Abschnitt 8.3.1.3. transient Felder :

Variablen können mit transient bis .__ gekennzeichnet sein. zeigen an, dass sie nicht Teil von .__ sind. Dauerzustand eines Objekts.

Beispielsweise können Sie Felder haben, die von anderen Feldern abgeleitet sind und nur programmgesteuert ausgeführt werden sollten, anstatt den Status per Serialisierung beibehalten zu lassen. 

Hier ist eine GalleryImage-Klasse, die ein Bild und ein vom Bild abgeleitetes Miniaturbild enthält:

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 ist thumbnailImage ein Miniaturbild, das durch Aufrufen der generateThumbnail-Methode generiert wird.

Das thumbnailImage-Feld ist als transient markiert. Daher wird nur das Original image serialisiert, anstatt sowohl das Originalbild als auch das Miniaturbild zu erhalten. Dies bedeutet, dass weniger Speicherplatz benötigt wird, um das serialisierte Objekt zu speichern. (Dies kann natürlich je nach den Anforderungen des Systems wünschenswert sein oder auch nicht - dies ist nur ein Beispiel.)

Zum Zeitpunkt der Deserialisierung wird die Methode readObject aufgerufen, um alle erforderlichen Vorgänge auszuführen, um den Zustand des Objekts auf den Zustand zurückzusetzen, in dem die Serialisierung stattgefunden hat. Hier muss die Miniaturansicht generiert werden, sodass die readObject-Methode überschrieben wird, sodass die Miniaturansicht durch Aufrufen der generateThumbnail-Methode generiert wird.

Weitere Informationen finden Sie im Abschnitt Die Geheimnisse der Java-Serialisierungs-API (der ursprünglich im Sun Developer Network verfügbar war). Dort wird die Verwendung von erläutert und ein Szenario dargestellt, in dem das transient-Schlüsselwort verwendet wird, um die Serialisierung zu verhindern bestimmter Felder.

1515
coobird

Bevor Sie das Schlüsselwort transient verstehen, müssen Sie das Konzept der Serialisierung verstehen. Wenn der Leser über die Serialisierung Bescheid weiß, überspringen Sie bitte den ersten Punkt.

Was ist Serialisierung?

Serialisierung ist der Prozess, bei dem der Status des Objekts dauerhaft bleibt. Das heißt, der Zustand des Objekts wird in einen Bytestrom umgewandelt, der zum Bestehen (z. B. Speichern von Bytes in einer Datei) oder zum Übertragen (z. B. Senden von Bytes über ein Netzwerk) verwendet wird. Auf dieselbe Weise können wir die Deserialisierung verwenden, um den Zustand des Objekts aus Bytes zurückzuholen. Dies ist eines der wichtigsten Konzepte bei der Java-Programmierung, da die Serialisierung hauptsächlich bei der Netzwerkprogrammierung verwendet wird. Die Objekte, die über das Netzwerk übertragen werden müssen, müssen in Bytes umgewandelt werden. Zu diesem Zweck muss jede Klasse oder Schnittstelle die Serializable -Schnittstelle implementieren. Es ist eine Marker-Schnittstelle ohne Methoden.

Was ist nun das transient-Schlüsselwort und sein Zweck?

Standardmäßig werden alle Objektvariablen in einen permanenten 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 transient deklarieren. Wenn die Variable als transient deklariert ist, wird sie nicht beibehalten. Dies ist der Hauptzweck des transient-Schlüsselworts.

Ich möchte die obigen zwei Punkte mit dem folgenden Beispiel erklären:

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 folgende sein:

First Name : Steve
Middle Name : null
Last Name : Jobs

Middle Name ist als transient deklariert und wird daher nicht im permanenten Speicher gespeichert.

Quelle

386
Rahul Saxena

Damit Sie Variablen definieren können, die Sie nicht serialisieren möchten. 

In einem Objekt haben Sie möglicherweise Informationen, die Sie nicht serialisieren/persistieren möchten (z. B. einen Verweis auf ein übergeordnetes Fabrikobjekt), oder die Serialisierung ist möglicherweise nicht sinnvoll. Wenn Sie diese als "transient" markieren, werden diese Felder vom Serialisierungsmechanismus ignoriert.

80
Brian Agnew

Mein kleiner Beitrag:

Was ist ein vorübergehendes Feld?
Grundsätzlich ist jedes Feld, das mit dem Schlüsselwort transient geändert wurde, ein Übergangsfeld.

Warum werden in Java transiente Felder benötigt?
Mit dem Schlüsselwort transient können Sie den Serialisierungsprozess steuern und einige Objekteigenschaften von diesem Prozess ausschließen. Der Serialisierungsprozess wird verwendet, um Java-Objekte zu persistieren, meistens, damit deren Status 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 vorübergehend markieren?
Nun kennen wir den Zweck des transient-Schlüsselworts und der Übergangsfelder. Es ist wichtig zu wissen, welche Felder als Übergang markiert werden sollen. Statische Felder werden auch nicht serialisiert, sodass das entsprechende Schlüsselwort auch den Trick ausführen würde. Dies könnte jedoch das Klassendesign zerstören. Hier kommt das Schlüsselwort transient zur Rettung. Ich versuche, nicht zuzulassen, dass Felder, deren Werte von anderen abgeleitet werden können, serialisiert werden, also markiere ich sie als transient. Wenn Sie ein Feld namens interest haben, dessen Wert aus anderen Feldern berechnet werden kann (principal, rate & time), müssen Sie es nicht serialisieren.

Ein weiteres gutes Beispiel ist der Artikel Word zählt. Wenn Sie einen gesamten Artikel speichern, müssen Sie die Word-Anzahl wirklich nicht speichern, da sie berechnet werden kann, wenn der Artikel "deserialisiert" wird. Oder über Logger nachdenken; Logger-Instanzen müssen fast nie serialisiert werden, sodass sie transient gemacht werden können.

31
Shreyos Adikari

Eine Variable transient ist eine Variable, die möglicherweise nicht serialisiert wird. 

Ein Beispiel, wenn dies nützlich sein könnte, sind Variablen, die nur im Kontext einer bestimmten Objektinstanz sinnvoll sind und die nach dem Serialisieren und Deserialisieren des Objekts ungültig werden. In diesem Fall ist es sinnvoll, dass diese Variablen stattdessen null werden, damit Sie sie bei Bedarf mit nützlichen Daten neu initialisieren können. 

21
Adrian Grigore

transient wird verwendet, um anzuzeigen, dass ein Klassenfeld nicht serialisiert werden muss . Das beste Beispiel ist wahrscheinlich ein Thread-Feld. Es gibt normalerweise keinen Grund, eine Thread zu serialisieren, da ihr Zustand sehr "flussspezifisch" ist. 

13
Andrei Ciobanu

Andere Serialisierungssysteme als das native Java-System können diesen Modifikator verwenden. Der Ruhezustand wird beispielsweise keine Felder beibehalten, die mit @Transient oder dem Transient - Modifikator markiert sind. Terracotta respektiert auch diesen Modifikator.

Ich glaube, die bildliche Bedeutung des Modifizierers ist "dieses Feld ist nur für die Verwendung im Arbeitsspeicher gedacht. Bewahren Sie es nicht auf und verschieben Sie es außerhalb dieses bestimmten VM auf irgendeine Weise. Sie können sich also nicht auf den Wert in einem anderen VM - Speicherbereich verlassen. Ähnlich wie volatile können Sie sich nicht auf bestimmte Speicher- und Thread-Semantiken verlassen.

12
DragonFax

Denn nicht alle Variablen sind serialisierbar

8
Silfverstrom

Bevor ich auf diese Frage antworte, muss ich Ihnen das 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 physischen Datenträgern (Datei, ...) gespeichert wird, muss das Objekt "serialisiert" werden. Die Serialisierung konvertiert Byte-Statusobjektserien. 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 NICHT TRANSFERT/SAVED Feld dieses Objekts SO wollen, können Sie Schlüsselwort verwenden. transient 

private transient attr2;

Beispiel

Dies ist erforderlich, wenn Sie keine sensiblen Daten zur Serialisierung freigeben möchten.

3
setzamora

Vereinfacht gesagt, das vorübergehende Java-Schlüsselwort schützt die Felder vor den Serialize-Objekten als ihre nicht transienten Felder.

In diesem Code-Snippet unserer abstrakten Klasse BaseJob implementieren wir die serialisierbare Schnittstelle. Wir gehen von BaseJob aus, aber wir müssen die entfernten und lokalen Datenquellen nicht serialisieren. Serialisieren Sie nur die Felder organisationsname 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;

   }
}
1
nyulan

Wie bei Google Vorübergehende Bedeutung == nur für kurze Zeit; unbeständig.

Wenn Sie in Java etwas Transient machen möchten, verwenden Sie ein transientes Schlüsselwort.

F: Wo ist Transient zu verwenden?  

A: Im Allgemeinen können in Java Daten in Dateien gespeichert werden, indem sie in Variablen erfasst und in Variablen geschrieben werden. Dieser Vorgang wird als Serialisierung bezeichnet. Wenn wir nun verhindern möchten, dass variable Daten in eine Datei geschrieben werden, würden wir diese Variable als vorübergehend definieren.

transient int result=10;

Hinweis: Übergangsvariablen können nicht lokal sein.

1
Mateen

Geben Sie noch ein Beispiel, um die Dinge klarer zu machen. Bitte lesen Sie die akzeptierte Antwort. Hier erkläre ich nur ein weiteres Beispiel.

    class Employee{
    String name;
    Date dob;
    transient int age;
    public int calculateAge(Date dob){
        int age = 0;
        //calculate age based on Date of birth
        return age;
    }
}

Hier im obigen Beispiel habe ich "Alter" als vergänglich gemacht. Wenn ich ein Alter in eine Datei schreibe, muss dessen Wert nicht gespeichert werden. Ich habe hier eine Funktion, die das Alter basierend auf DOB berechnet. Wir können Transienten für die Member-Variablen verwenden, die nicht auf die Festplatte geschrieben werden sollen. 

Ich hoffe es hilft.!

0
nandeesh

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);
    }
}
0
Habeeb Perwad