Maison >Java >javaDidacticiel >Analyse de l'utilisation du mot-clé transitoire en Java (code)

Analyse de l'utilisation du mot-clé transitoire en Java (code)

不言
不言original
2018-09-08 17:02:251961parcourir

Le contenu de cet article concerne l'analyse de l'utilisation (code) du mot-clé transient en Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1. Le rôle et l'utilisation des transitoires

Tant qu'un objet implémente l'interface Serilisable, l'objet peut être sérialisé, tant que la classe l'implémente Interface sérilisable, toutes les propriétés et méthodes de cette classe seront automatiquement sérialisées.

Cependant, dans le processus de développement réel, nous rencontrons souvent de tels problèmes. Certains attributs de cette classe doivent être sérialisés, tandis que d'autres n'ont pas besoin d'être sérialisés.

(1) Si un utilisateur dispose d'informations sensibles (telles que mot de passe, numéro de carte bancaire, etc.), pour des raisons de sécurité, il ne souhaite pas opérer sur le réseau (implique principalement des opérations de sérialisation, locales le cache de sérialisation s'applique également) est transmise en les variables correspondant à ces informations peuvent être ajoutées avec le mot-clé transient . En d'autres termes, le cycle de vie de ce champ n'existe que dans la mémoire de l'appelant et ne sera pas écrit sur le disque à des fins de persistance.

(2) Les valeurs des champs de la classe peuvent être dérivées en fonction d'autres champs. Par exemple, une classe rectangulaire a trois attributs : longueur, largeur, surface (juste un exemple, généralement pas conçu de cette façon). ), puis dans la sérialisation À l'heure actuelle, il n'est pas nécessaire que l'attribut Area soit sérialisé

En bref, le mot-clé transient de Java nous offre une certaine commodité. Il vous suffit d'implémenter l'interface Serilisable et d'ajouter le mot-clé. avant les attributs qui n'ont pas besoin d'être sérialisés. Transitoire, lors de la sérialisation de l'objet, cet attribut ne sera pas sérialisé vers la destination spécifiée.

L'exemple de code est le suivant :

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;
    }
 
}

La sortie est

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

Le champ du mot de passe est nul, indiquant qu'aucune information n'est obtenue du fichier pendant désérialisation.

2. Résultats de l'utilisation transitoire

1) Une fois qu'une variable est modifiée par transitoire, la variable ne fera plus partie de la persistance de l'objet, et le contenu du La variable ne peut pas être sérialisée après la sérialisation. Obtenez l'accès.

2) Une variable statique ne peut pas être sérialisée, qu'elle soit modifiée ou non par un transitoire.

3) Le mot-clé transient modifie la portée ne peut modifier que les variables, mais pas les méthodes et les classes . Notez que les variables locales ne peuvent pas être modifiées par le mot clé transient. Si la variable est une variable de classe définie par l'utilisateur, la classe doit implémenter l'interface Serialisable.

Le deuxième point peut prêter à confusion pour certaines personnes, car on constate qu'après avoir ajouté le mot-clé static avant le champ nom d'utilisateur dans la classe User, le résultat de l'exécution du programme reste inchangé, c'est-à-dire que le nom d'utilisateur statique est également lire comme « Alexia » « Eh bien, cela ne contredit-il pas le troisième point ? C'est effectivement le cas : le troisième point est effectivement correct (une variable statique ne peut pas être sérialisée qu'elle soit modifiée ou non par un transitoire Après désérialisation, la valeur de la variable statique username dans la classe est la variable statique correspondante). dans la JVM actuelle La valeur de la variable, cette valeur est obtenue par désérialisation dans la JVM , vous n'y croyez pas ? D'accord, laissez-moi le prouver ci-dessous :

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;
    }
 
}

Le résultat en cours d'exécution est :

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

Cela montre que la valeur de la variable statique username dans la classe après désérialisation est la valeur statique correspondante dans la JVM actuelle, la valeur de la variable est le jmwang modifié, pas la valeur Alexia lors de la sérialisation.

3. Détails de l'utilisation transitoire - les variables modifiées par le mot-clé transient ne peuvent-elles vraiment pas être sérialisées ?

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();
    }
}

La variable de contenu sera-t-elle sérialisée ? D'accord, j'affiche toutes les réponses, oui, le résultat courant est :

1

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

1

Oui, je serai sérialisé, que je sois modifié ou non avec le mot-clé transient

Pourquoi cela ne signifie-t-il pas que les variables de classe ne peuvent pas être sérialisées après avoir été modifiées par le mot-clé transient ?

En Java, la sérialisation d'objets peut être réalisée en implémentant deux interfaces :

(1) Si l'interface Serialisable est implémentée, toute sérialisation sera effectuée automatiquement

(2) Si l'interface Externalisable est implémentée, rien ne peut être sérialisé automatiquement. Vous devez spécifier manuellement les variables à sérialiser dans la méthode writeExternal

Cela n'a rien à voir avec le fait qu'elles soient transitoires. La modification n'a rien à voir là-dedans

. Par conséquent, le deuxième exemple génère le contenu initialisé de la variable content, et non null.

Recommandations associées :

Résumé de l'utilisation des mots clés transitoires Java


Résumé de l'exemple de code d'utilisation transitoire Java

Explication sur l'utilisation de base du mot-clé synchronisé dans la programmation multi-thread Java

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn