Hélas, bien que je connaisse très bien Java, il y a beaucoup de points de base de Java que je ne connais pas. Par exemple, je n'avais jamais utilisé le mot-clé transient auparavant, donc je ne savais pas à quoi il sert. Aujourd'hui, en passant un test écrit, j'ai trouvé une question à ce sujet, alors j'ai pris un peu de temps pour organiser l'utilisation du mot-clé transient et améliorer mes connaissances~~~ Bon, assez de bêtises, commençons ci-dessous :

1. La fonction et l'utilisation de transient

Nous savons tous que tant qu'un objet implémente l'interface Serializable, l'objet peut être sérialisé. Le mode de sérialisation de Java offre de nombreuses commodités aux développeurs. Nous n'avons pas besoin de nous soucier du processus de sérialisation spécifique ; tant que la classe implémente l'interface Serializable, toutes les propriétés et méthodes de la classe seront automatiquement sérialisées.

Cependant, dans le développement réel, nous rencontrons souvent ce problème : certaines propriétés d'une classe doivent être sérialisées, tandis que d'autres non. Par exemple, si un utilisateur possède des informations sensibles (comme des mots de passe, des numéros de carte bancaire, etc.), pour des raisons de sécurité, nous ne voulons pas qu'elles soient transmises lors d'opérations réseau (impliquant principalement des opérations de sérialisation ; la mise en cache de sérialisation locale s'applique également). Les variables correspondant à ces informations peuvent être marqué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 disque pour la persistance.

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

Exemple

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 Utilisez le mot-clé transient pour ne pas sérialiser une variable * Notez que lors de la lecture, l'ordre de lecture des données doit être cohérent avec l'ordre dans lequel les données ont été stockées * * @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("lire avant Serializable: "); System.out.println("nom d'utilisateur: " + user.getUsername()); System.err.println("mot de passe : " + user.getPasswd()); try { ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream("C:/user.txt")); os.writeObject(user); //Écrire l'objet User dans un fichier 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(); //Lire les données User depuis le flux is.close(); System.out.println("\nlu après Serializable : "); System.out.println("nom d'utilisateur: " + user.getUsername()); System.err.println("mot de passe : " + 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 mot de passe est null, ce qui indique qu'aucune information n'a été obtenue à partir du fichier lors de la désérialisation.

2. Récapitulatif de l'utilisation de transient

1) Une fois qu'une variable est modifiée par transient, la variable ne fait plus partie de la persistance de l'objet, et le contenu de la variable n'est pas accessible après la sérialisation.

2) Le mot-clé transient ne peut modifier que des variables, pas des méthodes ni des 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, alors cette classe doit implémenter l'interface Serializable.

3) Une variable modifiée par le mot-clé transient ne peut plus être sérialisée. Une variable static ne peut pas être sérialisée, qu'elle soit modifiée ou non par transient.

Certaines personnes peuvent être perplexes face au troisième point, car elles constatent qu'après avoir ajouté le mot-clé static devant le champ username dans la classe User, la sortie du programme reste inchangée ; c'est-à-dire que le username static est également lu comme "Alexia". Cela ne contredit-il pas le troisième point ? En fait, voici comment cela se passe : le troisième point est bien correct (une variable static ne peut pas être sérialisée, qu'elle soit modifiée ou non par transient). Après la désérialisation, la valeur de la variable static username dans la classe est la valeur de la variable static correspondante dans la JVM actuelle. Cette valeur provient de la JVM, et non de la désérialisation. Vous ne me croyez pas ? Très bien, laissez-moi le prouver ci-dessous :

Exemple

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 Utiliser le mot-clé transient pour ne pas sérialiser une variable * Notez que lors de la lecture, l'ordre de lecture des données doit être cohérent avec l'ordre dans lequel les données ont été stockées * * @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("lire avant Serializable: "); System.out.println("nom d'utilisateur: " + user.getUsername()); System.err.println("mot de passe : " + user.getPasswd()); try { ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream("C:/user.txt")); os.writeObject(user); //Écrire l'objet User dans un fichier os.flush(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { //Modifier la valeur de username avant la désérialisation User.username = "jmwang"; ObjectInputStream is = new ObjectInputStream(new FileInputStream( "C:/user.txt")); user = (User) is.readObject(); //Lire les données User à partir du flux is.close(); System.out.println("\nlu après Serializable: "); System.out.println("nom d'utilisateur: " + user.getUsername()); System.err.println("mot de passe : " + 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 d'exécution est :

read before Serializable: 
username: Alexia
password: 123456

read after Serializable: 
username: jmwang
password: null

Cela montre qu'après désérialisation, la valeur de la variable statique username dans la classe est la valeur de la variable statique correspondante dans la JVM actuelle, qui est jmwang après modification, et non la valeur Alexia issue de la sérialisation.

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

Considérez l'exemple suivant :

Exemple

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 Utilisation de l'interface Externalizable * * @author Alexia * @date 2013-10-15 * */ public class ExternalizableTest implements Externalizable { private transient String content = "Oui, je serai sérialisé, que je sois modifié ou non par le mot-clé 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 content sera-t-elle sérialisée ? Très bien, j'ai déjà affiché la réponse. Oui, le résultat de l'exécution est :

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

Pourquoi cela ? N'avons-nous pas dit qu'après qu'une variable de classe est modifiée par le mot-clé transient, elle ne peut pas être sérialisée ?

Nous savons qu'en Java, la sérialisation d'objets peut être réalisée en implémentant deux interfaces. Si l'interface Serializable est implémentée, toute la sérialisation sera effectuée automatiquement. Si l'interface Externalizable 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, qu'elles soient modifiées ou non par transient. Par conséquent, dans le deuxième exemple, la sortie est le contenu initialisé de la variable content, et non null.

Source : http://www.cnblogs.com/lanxuezaipiao/p/3369962.html