Java transient keywords
1. The function and usage method of transient
We all know that as long as an object implements the Serilizable interface, the object can be serialized. This serialization model of Java provides a lot of convenience for developers. We do not have to relate to the specific serialization process. As long as this class implements the Serilizable interface, all properties and methods of this class will be automatically serialized.
However, in the actual development process, we often encounter such problems. Some properties of this class need to be serialized, while other properties do not need to be serialized. For example, if a user has some sensitive information (such as passwords, bank card numbers, etc.), for security reasons, he does not want to be transmitted in network operations (mainly involving serialization operations, local serialization cache is also applicable), and the variables corresponding to these information can be added with the transient keyword. In other words, the life cycle of this field is only in the caller's memory and is not written to disk for persistence.
In short, Java's transient keyword provides us with convenience. You only need to implement the Serilizable interface and add the keyword transient before the attributes that do not need to be serialized. When serializing the object, this attribute will not be serialized to the specified destination.
The example code is as follows:
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 transient keywords to not serialize a variable* Note that when reading, the order of reading data must be consistent with the order of storing data* * @author Alexia * @date 2013-10-15 * http://www.manongjc.com/article/1609.html */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 into the 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 User's 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; }}The output is:
read before Serializable: username: Alexiapassword: 123456read after Serializable: username: Alexiapassword: null
The password field is null, which means that no information was obtained from the file during deserialization.
2. Transient usage summary
1) Once the variable is modified by transient, the variable will no longer be part of the object's persistence, and the contents of the variable cannot be accessed after serialization.
2) The transient keyword can only modify variables, but not methods and classes. Note that local variables cannot be modified by transient keywords. If a variable is a user-defined class variable, the class needs to implement the Serializable interface.
3) Variables modified by the transient keyword can no longer be serialized. A static variable cannot be serialized regardless of whether it is modified by transient.
The third point may be confusing, because I found that after adding the static keyword to the username field in the User class, the program run result remains unchanged, that is, the username of static type is also read as "Alexia". Isn't this contradictory to the third point? Actually, it is like this: the third point is indeed correct (a static variable cannot be serialized regardless of whether it is modified by transient). After deserialization, the username of the static variable in the class is the value of the corresponding static variable in the current JVM. This value is not derived from deserialization in the JVM. Don't believe it? OK, let me prove it below:
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 transient keywords to not serialize a variable* Note that when reading, the order of reading data must be consistent with the order of storing data* * @author Alexia * @date 2013-10-15 * http://www.manongjc.com */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 into the file os.flush(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { // Change the username value before deserialization User.username = "jmwang"; ObjectInputStream is = new ObjectInputStream(new FileInputStream( "C:/user.txt")); user = (User) is.readObject(); // Read User's 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: Alexiapassword: 123456read after Serializable: username: jmwangpassword: null
This means that the value of the username of the static variable in the deserialized class is the value of the corresponding static variable in the current JVM, which is the modified jmwang, not the value Alexia during serialization.
3. Transient usage details - Can variables modified by the transient keyword really be serialized?
Think about the following examples:
import java.io.Externalizable;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;/** * @descripton Use of 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 or not"; @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? OK, I've outputted all the answers, yes, the result is:
Yes, I will be serialized, regardless of whether I am modified by the transient keyword or not
Why is this? Isn't it said that the variables of the class will not be serialized after being modified by the transient keyword?
We know that in Java, object serialization can be implemented 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 variable to be serialized in the writeExternal method, which has nothing to do with whether it is modified by transient. Therefore, the second example outputs the content initialized by the variable content, not null.
Thank you for reading, I hope it can help you. Thank you for your support for this site!