Use note for Java transient keywords
1. Functions and usage of transient
We all know that an object can be serialized as long as the Serilizable interface is implemented. This serialization mode of java provides developers with a lot of convenience, so we don't have to worry about the specific serialization process, as long as this class implements the Serilizable interface, all attributes and methods of this class will be automatically serialized.
However, in the actual development process, we often encounter this problem. Some attributes of this class need to be serialized, while other attributes do not need to be serialized. For example, if a user has some sensitive information (such as passwords and bank card numbers), the user does not want to operate on the network for security reasons (mainly involves serialization operations, and the local serialization cache is also applicable) the transient keyword can be added to the variables corresponding to the information. In other words, the lifecycle of this field only exists in the caller's memory and is not written to the disk for persistence.
In short, the transient keyword of java provides convenience for us. You only need to implement the Serilizable interface and add the transient keyword before the attribute that does not need to be serialized. When serializing the object, this attribute will not be serialized to the specified destination.
The sample 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 Do not serialize a variable using the transient keyword * when reading, the Data Reading sequence must be consistent with the data storage sequence ** @ 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 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 the User data from the stream is. close (); System. out. println (read 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 ;}}
View Code
Output:
read before Serializable: username: Alexiapassword: 123456read after Serializable: username: Alexiapassword: null
The password field is null, indicating that information is not obtained from the file during deserialization.
2. Summary of transient usage
1) Once a variable is modified by transient, the variable will no longer be part of Object persistence, and the variable content 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 the transient keyword. If the variable is a user-defined class variable, the class must implement the Serializable interface.
3) variables modified by the transient keyword can no longer be serialized. A static variable cannot be serialized no matter whether it is modified by the transient or not.
Third, some people may be confused, because the program running results remain unchanged after the static keyword is added to the username field in the User class, that is, the static username is also read as "Alexia, isn't this a conflict with the third point? This is actually true: the third point is true (a static variable cannot be serialized no matter whether it is modified by transient ), in the post-deserialization class, the value of the static variable username is the value of the corresponding static variable in the current JVM. This value is obtained from non-deserialization In the JVM. Don't believe it? Okay, let me prove it:
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 Do not serialize a variable using the transient keyword * when reading, the Data Reading sequence must be consistent with the data storage sequence ** @ 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 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 the User data from the stream is. close (); System. out. println (read 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 ;}}
View Code
The running result is:
read before Serializable: username: Alexiapassword: 123456read after Serializable: username: jmwangpassword: null
This indicates that the username value of the static variable in the Post-deserialization class is the value of the static variable corresponding to the current JVM. It is the modified jmwang instead of the value Alexia during serialization.
3. transient usage details-is it true that variables modified by the transient keyword cannot be serialized?
Consider the following 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 Externalizable interface ** @ author Alexia * @ date 2013-10-15 **/public class ExternalizableTest implements Externalizable {private transient String content = Yes, I will be serialized, whether or not I have been 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? Okay, I output all the answers. Yes, the running result is:
Yes, I will be serialized, whether or not I have been modified by the transient keyword
Why? Isn't the class variable serialized after being modified by the transient keyword?
We know that in Java, Object serialization can be implemented through two interfaces. If the Serializable interface is implemented, all serialization will be performed automatically, if the Externalizable interface is implemented, nothing can be automatically serialized. 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 instead of null.