Java transient keyword specification and example code

  • 2020-05-19 04:59:15
  • OfStack

Java transient keyword

1. Function and use of transient

We all know that an object can be serialized as long as it implements the Serilizable interface. The serialization mode of java provides a lot of convenience for developers. We don't have to worry about the specific serialization process, as long as this class implements the Serilizable interface, all the properties and methods of this class will be serialized automatically.

In actual development process, however, we often encounter such problems, some properties of this class to serialization, and other attributes do not need to be serialized, for example, if a user has a sensitive information (such as passwords, bank card number, etc.), to be on the safe side, do not want in network operation (mainly involves serialized operation, local serialization cache is applicable) by the transmission, and the information can be combined with the corresponding variable transient keyword. In other words, the lifetime of the field is only in the caller's memory and is not persisted to disk.

In summary, the transient keyword of java provides convenience for us. You only need to implement the Serilizable interface and add the keyword transient before the properties that do not need to be serialized. When you serialize an object, this property will not be serialized to the specified destination.

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 The keyword does not serialize a variable 
 *     Pay attention to the order in which the data is read 1 Always keep the data in the order in which it is stored 1 to 
 *    
 * @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); //  will User Object is written 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 from the stream User The data of 
      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: Alexia
password: 123456

read after Serializable: 
username: Alexia
password: null

The password field is null, indicating that no information was retrieved from the file at all when deserialized.

2. transient USES summaries

1) when a variable is modified by transient, the variable will no longer be part 1 of the object persistence, and the contents of the variable cannot be accessed after serialization.

2) the transient keyword can only modify variables, 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 needs to implement the Serializable interface.

3) a variable modified by transient keyword can no longer be serialized, and a static variable cannot be serialized whether or not it is modified by transient.

Point 3 May be confusing to some people, because when the static keyword is added before the username field in the User class, the program still runs the same, that is, username of the static type is also pronounced as "Alexia". Is this not inconsistent with point 3? In fact, it is like this: point 3 is indeed true (a static variable cannot be serialized regardless of whether it is modified by transient). The value of static type variable username in the class after deserialization is the value of the corresponding static variable in the current JVM. Well, 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  use transient The keyword does not serialize a variable 
 *     Pay attention to the order in which the data is read 1 Always keep the data in the order in which it is stored 1 to 
 *    
 * @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); //  will User Object is written to a file 
      os.flush();
      os.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    try {
      //  Change before deserialization username The value of the 
      User.username = "jmwang";

      ObjectInputStream is = new ObjectInputStream(new FileInputStream(
          "C:/user.txt"));
      user = (User) is.readObject(); //  Read from the stream User The data of 
      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 means that the value of the static type variable username in the deserialized class is the value of the corresponding static variable in the current JVM, which is the modified jmwang, rather than the serialized Alexia value.

3. transient usage details -- can a variable modified by the transient keyword really not 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 Use of interface 
 * 
 * @author Alexia
 * @date 2013-10-15
 *
 */
public class ExternalizableTest implements Externalizable {

  private transient String content = " Yes, I will be serialized whether I am or not transient Keyword modification ";

  @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? Well, I've printed out all the answers, and, yes, the result is:

Yes, I will be serialized, whether or not I am modified by the transient keyword

Why is it that class variables cannot be serialized after being modified by the transient keyword?

We know in Java, object serialization can be implemented through two interfaces to, if the implementation is Serializable interface, then all the serialization will automatically, if the implementation is Externalizable interface, then nothing can automatic serialization, need to manually specify in writeExternal method to serialize variables, this has nothing to do with whether be transient modification. So the second example outputs the contents initialized by the variable content, not null.

Thank you for reading, I hope to help you, thank you for your support of this site!


Related articles: