Heim  >  Artikel  >  Java  >  Zusammenfassung der Verwendung vorübergehender Java-Schlüsselwörter

Zusammenfassung der Verwendung vorübergehender Java-Schlüsselwörter

黄舟
黄舟Original
2017-02-23 10:22:251447Durchsuche

Hey, obwohl ich mit Java am besten vertraut bin, kenne ich nicht viele grundlegende Java-Kenntnisse. Das Schlüsselwort „transient“ wurde beispielsweise noch nie verwendet, daher weiß ich nicht, welche Funktion es hat eine Frage, als ich heute den schriftlichen Test gemacht habe. Darum geht es, also habe ich einige Zeit damit verbracht, die Verwendung des Schlüsselworts „transient“ zu klären und mich auf den neuesten Stand zu bringen~~~Okay, ohne weitere Umschweife, fangen wir an:

1. Transiente Funktion und Verwendung

Wir alle wissen, dass das Objekt serialisiert werden kann, solange es die Serilisierbare Schnittstelle implementiert. Dieser Serialisierungsmodus von Java bietet Entwicklern viele Annehmlichkeiten Wir müssen uns nicht um die spezifische Reihenfolge kümmern, solange diese Klasse die Serilisierbare Schnittstelle implementiert.

Im eigentlichen Entwicklungsprozess stoßen wir jedoch häufig auf ein solches Problem. Einige Attribute dieser Klasse müssen serialisiert werden, während andere Attribute beispielsweise nicht serialisiert werden müssen Aus Sicherheitsgründen wird nicht erwartet, dass Informationen (wie Passwörter, Bankkartennummern usw.) während des Netzwerkbetriebs übertragen werden (hauptsächlich bei Serialisierungsvorgängen, auch lokaler Serialisierungs-Cache ist anwendbar). Die diesen Informationen entsprechenden Variablen können hinzugefügt werden mit dem Schlüsselwort transient . Mit anderen Worten: Der Lebenszyklus dieses Felds existiert nur im Speicher des Aufrufers und wird nicht zur Persistenz auf die Festplatte geschrieben.

Kurz gesagt, das transiente Schlüsselwort von Java bietet uns Komfort. Sie müssen nur die Serilisierbare Schnittstelle implementieren und das Schlüsselwort transient vor den Eigenschaften hinzufügen, die nicht serialisiert werden müssen wird 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关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 * @author Alexia
 * @date  2013-10-15
 */
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 Serialisierung überhaupt keine Informationen aus der Datei abgerufen werden.

2. Zusammenfassung der vorübergehenden Verwendung

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

2) Das Schlüsselwort transient 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.

3) Variablen, die durch das Schlüsselwort transient geändert wurden, können nicht mehr serialisiert werden. Eine statische Variable kann nicht serialisiert werden, unabhängig davon, ob sie durch transient geändert wurde oder nicht.

Der dritte 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 wahr (eine statische Variable kann nicht serialisiert werden, unabhängig davon, ob sie durch einen Transienten geändert wird. Nach der Deserialisierung ist der Wert der statischen Variablen Benutzername in der Klasse der Wert der entsprechenden statischen Variablen). In der aktuellen JVM ist dieser Wert von der JVM abgeleitet und nicht von der Deserialisierung, glauben Sie es nicht? Nun, 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关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 * @author Alexia
 * @date  2013-10-15
 */
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

Das zeigt sich im Unterricht danach Deserialisierung Der Wert der statischen Variablen Benutzername ist der Wert der entsprechenden statischen Variablen in der aktuellen JVM, bei der es sich um den geänderten JMwang handelt, nicht der Wert Alexia während der Serialisierung.

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

Betrachten Sie das folgende Beispiel:

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接口的使用
 * 
 * @author Alexia
 * @date 2013-10-15
 *
 */
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? Nun, ich gebe alle Antworten aus:

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



Warum ist das nicht so, dass die Klassenvariablen der Übergang sind? Schlüsselwort nach Änderung nicht serialisierbar?

Wir wissen, dass in Java die Objektserialisierung durch die Implementierung von zwei Schnittstellen erreicht werden kann. Wenn die Serialisierbare Schnittstelle implementiert ist, wird die gesamte Serialisierung automatisch durchgeführt. Wenn die Externalisierbare 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 durch transient geändert werden. Daher gibt das zweite Beispiel den initialisierten Inhalt der Variablen content aus, nicht null.

Das Obige ist die Zusammenfassung der vorübergehenden Verwendung von Java-Schlüsselwörtern. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).


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
Vorheriger Artikel:Dinge über Java GC (2)Nächster Artikel:Dinge über Java GC (2)