Heim  >  Artikel  >  Java  >  Nutzungsanalyse von transienten Schlüsselwörtern in Java (Code)

Nutzungsanalyse von transienten Schlüsselwörtern in Java (Code)

不言
不言Original
2018-09-08 17:02:251871Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Verwendungsanalyse (Code) des transienten Schlüsselworts. Ich hoffe, dass er für Freunde hilfreich ist.

1. Die Rolle und Verwendung von transient

Solange ein Objekt die Serilisierbare Schnittstelle implementiert, kann das Objekt serialisiert werden, solange die Klasse vorhanden ist implementiert es Serilisierbare Schnittstelle, alle Eigenschaften und Methoden dieser Klasse werden automatisch serialisiert.

Im eigentlichen Entwicklungsprozess stoßen wir jedoch häufig auf solche Probleme Einige Attribute dieser Klasse müssen serialisiert werden, während andere Attribute nicht serialisiert werden müssen:

(1) Wenn ein Benutzer über vertrauliche Informationen (z. B. Passwort, Bankkartennummer usw.) verfügt, möchte er aus Sicherheitsgründen nicht im Netzwerk arbeiten (beinhaltet hauptsächlich lokale Serialisierungsvorgänge). (es gilt auch der Serialisierungs-Cache) wird in übertragen. Die diesen Informationen entsprechenden Variablen können mit dem transienten Schlüsselwort hinzugefügt werden. Mit anderen Worten: Der Lebenszyklus dieses Felds existiert nur im Speicher des Aufrufers und wird nicht aus Gründen der Persistenz auf die Festplatte geschrieben.

(2) Die Feldwerte in der Klasse können basierend auf anderen Feldern abgeleitet werden. Eine rechteckige Klasse hat beispielsweise drei Attribute: Länge, Breite, Fläche (nur ein Beispiel, im Allgemeinen nicht so gestaltet). ), dann in der Serialisierung. Zu diesem Zeitpunkt ist keine Serialisierung des Bereichsattributs erforderlich.

Kurz gesagt, das transiente Schlüsselwort von Java bietet uns Komfort. Sie müssen nur die Serilisierbare Schnittstelle implementieren und das Schlüsselwort hinzufügen Vor den Attributen, die nicht serialisiert werden müssen, wird diese Eigenschaft beim Serialisieren des Objekts nicht an das angegebene Ziel serialisiert.

Der Beispielcode lautet wie folgt:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
/**
 * @description 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *       
 */
public class TransientTest {
 
    public static void main(String[] args) {
 
        User user = new User();
        user.setUsername("Alexia");
        user.setPasswd("123456");
 
        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());
 
        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("C:/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();
 
            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
 
class User implements Serializable {
    private static final long serialVersionUID = 8294180014912103005L;  
 
    private String username;
    private transient String passwd;
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPasswd() {
        return passwd;
    }
 
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
 
}

Die Ausgabe ist

read before Serializable: 
username: Alexia
password: 123456
read after Serializable: 
username: Alexia
password: null

Das Passwortfeld ist null, was darauf hinweist, dass während der Deserialisierung keine Informationen aus der Datei abgerufen werden.

2. Ergebnisse der vorübergehenden Verwendung

1) Sobald eine Variable durch eine vorübergehende Änderung geändert wird, ist die Variable nicht mehr Teil der Objektpersistenz und der Inhalt von Die Variable kann nach der Serialisierung nicht serialisiert werden.

2) Eine statische Variable kann nicht serialisiert werden, unabhängig davon, ob sie durch einen Transienten geändert wird.

3) Das Schlüsselwort transient ändert den Bereich kann nur Variablen ändern, nicht jedoch Methoden und Klassen . Beachten Sie, dass lokale Variablen nicht durch das Schlüsselwort transient geändert werden können. Wenn es sich bei der Variablen um eine benutzerdefinierte Klassenvariable handelt, muss die Klasse die Serializable-Schnittstelle implementieren.

Der zweite Punkt kann für einige Leute verwirrend sein, da sich herausstellt, dass nach dem Hinzufügen des statischen Schlüsselworts vor dem Benutzernamenfeld in der Benutzerklasse das Ergebnis der Programmausführung unverändert bleibt, d. h. auch der statische Benutzername lesen als „Alexia“ „Nun, widerspricht das nicht dem dritten Punkt? Dies ist tatsächlich der Fall: Der dritte Punkt ist tatsächlich richtig (eine statische Variable kann nicht serialisiert werden, unabhängig davon, ob sie durch Transient geändert wird). Nach der Deserialisierung ist der Wert der statischen Variablen Benutzername in der Klasse die entsprechende statische Variable in der aktuellen JVM. Dieser Wert wird durch Deserialisierung in der JVM erhalten , glauben Sie es nicht? Okay, lassen Sie es mich unten beweisen:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
/**
 * @description 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 */
public class TransientTest {
 
    public static void main(String[] args) {
 
        User user = new User();
        user.setUsername("Alexia");
        user.setPasswd("123456");
 
        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());
 
        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("C:/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 在反序列化之前改变username的值
            User.username = "jmwang";
 
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();
 
            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
 
class User implements Serializable {
    private static final long serialVersionUID = 8294180014912103005L;  
 
    public static String username;
    private transient String passwd;
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPasswd() {
        return passwd;
    }
 
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
 
}

Das laufende Ergebnis ist:

read before Serializable: 
username: Alexia
password: 123456
read after Serializable: 
username: jmwang
password: null

Dies zeigt, dass der Wert der statischen Variablen Benutzername in der Klasse nach der Deserialisierung der Wert der entsprechenden statischen Variablen ist In der aktuellen JVM handelt es sich um den geänderten JMwang, nicht um den Wert Alexia während der Serialisierung.

3. Details zur transienten Verwendung – können durch das transiente Schlüsselwort geänderte Variablen wirklich nicht serialisiert werden?

import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
 
/**
 * @descripiton Externalizable接口的使用
 *
 */
public class ExternalizableTest implements Externalizable {
 
    private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";
 
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(content);
    }
 
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        content = (String) in.readObject();
    }
 
    public static void main(String[] args) throws Exception {
 
        ExternalizableTest et = new ExternalizableTest();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test")));
        out.writeObject(et);
 
        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test")));
        et = (ExternalizableTest) in.readObject();
        System.out.println(et.content);
 
        out.close();
        in.close();
    }
}

Wird die Inhaltsvariable serialisiert? Okay, ich gebe alle Antworten aus, ja, das laufende Ergebnis ist:

1

是的,我将会被序列化,不管我是否被transient关键字修饰

1

Ja, ich werde serialisiert, unabhängig davon, ob ich mit dem Schlüsselwort transient

geändert werde

Warum bedeutet das nicht, dass Klassenvariablen nicht serialisiert werden können, nachdem sie durch das Schlüsselwort transient geändert wurden?

In Java kann die Objektserialisierung durch die Implementierung von zwei Schnittstellen erreicht werden:

(1) Wenn die Serializable-Schnittstelle implementiert ist, erfolgt die gesamte Serialisierung automatisch

(2) Wenn die Externalizable-Schnittstelle implementiert ist, kann nichts automatisch serialisiert werden. Sie müssen die zu serialisierenden Variablen manuell in der writeExternal-Methode angeben.

Dies hat nichts damit zu tun, ob sie vorübergehend ist. Modifikation hat damit nichts zu tun

. Daher gibt das zweite Beispiel den initialisierten Inhalt der Variablen content aus, nicht null.

Verwandte Empfehlungen:

Zusammenfassung der Java-Transient-Keyword-Nutzung


Beispielzusammenfassung für den Java-Transient-Nutzungscode

Erläuterung der grundlegenden Verwendung des synchronisierten Schlüsselworts in der Java-Multithread-Programmierung

Das obige ist der detaillierte Inhalt vonNutzungsanalyse von transienten Schlüsselwörtern in Java (Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn