Alas, although I am most familiar with Java, there are many basic Java knowledge points that I don't know. For example, I had never used the transient keyword before, so I didn't know what it does. Today, while doing a written test, I found a question about it, so I took some time to organize the usage of the transient keyword and improve my knowledge~~~ Alright, enough nonsense, let's begin below:

1. The function and usage of transient

We all know that as long as an object implements the Serializable interface, the object can be serialized. Java's serialization mode provides developers with many conveniences. We don't need to worry about the specific serialization process; as long as the class implements the Serializable interface, all properties and methods of the class will be automatically serialized.

However, in actual development, we often encounter this problem: some properties of a class need to be serialized, while other properties do not. For example, if a user has some sensitive information (such as passwords, bank card numbers, etc.), for security reasons, we do not want it to be transmitted during network operations (mainly involving serialization operations; local serialization caching also applies). The variables corresponding to this information can be marked with the transient keyword. In other words, the lifecycle of this field only exists in the caller's memory and will not be written to disk for persistence.

In short, Java's transient keyword provides us with convenience. You just need to implement the Serializable interface and add the transient keyword before the attributes that do not need to be serialized. When serializing the object, this attribute will not be serialized to the specified destination.

Example

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 Use the transient keyword to not serialize a variable * Note that when reading, the order of reading data must be consistent with the order in which the data was stored * * @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); //Write the User object to a file 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(); //Read the User data from the stream 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; } }

Output is:

read before Serializable: 
username: Alexia
password: 123456

read after Serializable: 
username: Alexia
password: null

The password field is null, indicating that no information was obtained from the file during deserialization.

2. Summary of transient usage

1) Once a variable is modified by transient, the variable is no longer part of the object's persistence, and the variable's content cannot be accessed after serialization.

2) The transient keyword can only modify variables, not methods or classes. Note that local variables cannot be modified by the transient keyword. If the variable is a user-defined class variable, then that class needs to implement the Serializable interface.

3) A variable modified by the transient keyword can no longer be serialized. A static variable cannot be serialized regardless of whether it is modified by transient.

Some people may be confused about the third point, because they find that after adding the static keyword before the username field in the User class, the program output remains unchanged; that is, the static username is also read out as "Alexia". Doesn't this contradict the third point? Actually, this is how it is: the third point is indeed correct (a static variable cannot be serialized regardless of whether it is modified by transient). After deserialization, the value of the static variable username in the class is the value of the corresponding static variable in the current JVM. This value comes from the JVM, not from deserialization. Don't believe it? Alright, let me prove it below:

Example

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 Use the transient keyword to not serialize a variable * Note that when reading, the order of reading data must be consistent with the order in which data was stored * * @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); //Write the User object to a file os.flush(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { //Change the value of username before deserialization User.username = "jmwang"; ObjectInputStream is = new ObjectInputStream(new FileInputStream( "C:/user.txt")); user = (User) is.readObject(); //Read the User data from the stream 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; } }

The running result is:

read before Serializable: 
username: Alexia
password: 123456

read after Serializable: 
username: jmwang
password: null

This shows that after deserialization, the value of the static variable username in the class is the value of the corresponding static variable in the current JVM, which is jmwang after modification, not the value Alexia from serialization.

3. Details of transient usage — Can variables modified by the transient keyword really not be serialized?

Consider the following example:

Example

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 Usage of the Externalizable interface * * @author Alexia * @date 2013-10-15 * */ public class ExternalizableTest implements Externalizable { private transient String content = "Yes, I will be serialized, regardless of whether I am modified by the transient keyword"; @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(); } }

Will the content variable be serialized? Alright, I have already output the answer. Yes, the running result is:

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

Why is this? Didn't we say that after a class variable is modified by the transient keyword, it cannot be serialized?

We know that in Java, object serialization can be achieved by implementing two interfaces. If the Serializable interface is implemented, all serialization will be performed automatically. If the Externalizable interface is implemented, nothing can be serialized automatically; you need to manually specify the variables to be serialized in the writeExternal method, regardless of whether they are modified by transient. Therefore, in the second example, the output is the initialized content of the variable content, not null.

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