Home  >  Article  >  Java  >  Usage analysis of transient keyword in Java (code)

Usage analysis of transient keyword in Java (code)

不言
不言Original
2018-09-08 17:02:251919browse

The content of this article is about the usage analysis (code) of the transient keyword in Java. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

1. The role and use of transient

As long as an object implements the Serilizable interface, the object can be serialized, as long as the class implements it 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 attributes of this class need to be serialized, while other attributes do not need to be serialized. Here are two examples:

(1) If a user has some sensitive information (such as password, bank card number, etc.), for security reasons, he does not want to operate on the network (mainly involves serialization operations, local serialization cache also applies) is transmitted, the variables corresponding to these information can be added with the transient keyword. In other words, the life cycle of this field only exists in the caller's memory and will not be written to disk for persistence.

(2) The field values ​​in the class can be derived based on other fields. For example, a rectangular class has three attributes: length, width, area (just an example, generally not designed this way), then in the serialization At this time, there is no need for the area attribute to be serialized;

In short, the transient keyword of java provides us with convenience. You only need to implement the Serilizable interface and add the keyword before the attributes that do not need to be serialized. Transient, 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 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *       
 */
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); // 将User对象写进文件
            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(); // 从流中读取User的数据
            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 obtained from the file during deserialization.

2. Results of transient use

1) Once a variable is modified by transient, the variable will no longer be part of the object persistence, and the content of the variable cannot be serialized after serialization. Get access.

2) A static variable cannot be serialized regardless of whether it is modified by transient.

3) The transient keyword modifies the scope, 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 needs to implement the Serializable interface.

The second point may be confusing to some people, because it is found that after adding the static keyword before the username field in the User class, the program running result remains unchanged, that is, the static username is also read as "Alexia" "Well, doesn't this contradict the third point? This is actually the case: 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 corresponding static variable in the current JVM. The value of the variable, this value is derived from the JVM and is not deserialized. Don’t believe it? Okay, 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 使用transient关键字不序列化某个变量
 *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
 *        
 */
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); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 在反序列化之前改变username的值
            User.username = "jmwang";
 
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            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 the value of the static variable username in the class after deserialization is the value of the corresponding static variable in the current JVM. It is the modified jmwang, not the value Alexia during serialization.

3. Details of transient use-can variables modified by the transient keyword really not be serialized?

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接口的使用
 *
 */
public class ExternalizableTest implements Externalizable {
 
    private transient String content = "是的,我将会被序列化,不管我是否被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();
    }
}

Will the content variable be serialized? Okay, I output all the answers, yes, the running result is:

1

Yes, I will be serialized regardless of whether I am modified by the transient keyword

Why is this? Doesn’t it mean that class variables cannot be serialized after being modified with the transient keyword?

In Java, the serialization of objects can be achieved by implementing two interfaces:

(1) If the Serializable interface is implemented, all serialization will It will be done automatically

(2) 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.

This has nothing to do with whether it is transient Modification has nothing to do with . Therefore, the second example outputs the initialized content of the variable content, not null.

Related recommendations:

Java transient keyword usage summary

Java-transient usage code example summary

Explanation on the basic usage of synchronized keyword in Java multi-thread programming

The above is the detailed content of Usage analysis of transient keyword in Java (code). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn