Java之transient关键字用法解读

1. transient 简介

java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

2. transient 作用

Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它,比如:当对象被序列化时(写入字节序列到目标文件)时,用户有一些敏感信息(如密码,银行卡号等)不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

3. transient 实例

定义一个类StudentInfo,用于刻画学生,StudentInfo有3个属性,分别为学号、姓名和密码,由于密码是敏感信息,在对学生对象进行持久化时,不希望密码被持久化(常用于银行系统)。因此,将密码属性用transient修饰。代码实例如下:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestModel
{
    public static void main(String[] args)
    {
        StudentInfo studentInfo = new StudentInfo(12345, "Jone", "ASDZXC123456");

        System.out.println(studentInfo.toString());
        // 序列化,将对象studentInfo序列化并写入文件(磁盘)
        try
        {
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("studentInfo.txt"));
            o.writeObject(studentInfo);
            o.close();
        }
        catch (Exception e)
        { 
            e.printStackTrace();
        }
        // 反序列化,将文件中的对象读取出来
        try
        {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("studentInfo.txt"));
            StudentInfo readUserInfo = (StudentInfo) in.readObject(); 
            System.out.println(readUserInfo.toString());
            in.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

class StudentInfo implements Serializable
{

    private static final long serialVersionUID = 6032595353588485049L;
    private int number;
    private String name;
    private transient String password;// 不希望被序列化,用transient修饰

    public StudentInfo(int number, String name, String password)
    {
        this.number = number;
        this.name = name;
        this.password = password;
    }

    public String toString()
    {
        return "number=" + number + ", name=" + name + ", password=" + password;
    }
}

执行结果:

number=12345, name=Jone, password=ASDZXC123456
number=12345, name=Jone, password=null

结果分析:

              很明显,transient 关键字修饰的属性password并没有被持久化,因此反序列化读出的结果为null。

4. transient 注意事项

  1,一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 
  2,transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。 
  3,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 
  

对于第三点,加上static之后,依然能把姓名输出。这是因为:反序列化后类中static型变量name的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。下例可说明,其值时JVM中得到的而不是反序列化得到的:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestModel
{
    public static void main(String[] args)
    {
        StudentInfo studentInfo = new StudentInfo(12345, "Jone", "ASDZXC123456");

        System.out.println(studentInfo.toString());
        // 序列化,将对象studentInfo序列化并写入文件(磁盘)
        try
        {
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("studentInfo.txt"));
            o.writeObject(studentInfo);
            o.close();
        }
        catch (Exception e)
        { 
            e.printStackTrace();
        }
        // 反序列化,将文件中的对象读取出来, 反序列化之前改变静态变量的值
        StudentInfo.setFlag("Shang-Hai");
        try
        {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("studentInfo.txt"));
            StudentInfo readUserInfo = (StudentInfo) in.readObject(); 
            System.out.println(readUserInfo.toString());
            in.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

class StudentInfo implements Serializable
{

    private static final long serialVersionUID = 6032595353588485049L;
    private static String flag = "Bei-Jing";
    private int number;
    private String name;
    private transient String password;// 不希望被序列化,用transient修饰

    public StudentInfo(int number, String name, String password)
    {
        this.number = number;
        this.name = name;
        this.password = password;
    }

    public String toString()
    {
        return "flag="+ flag + ", number=" + number + ", name=" + name + ", password=" + password;
    }
    
    public static void setFlag(String flag)
    {
        StudentInfo.flag = flag;
    }
}

执行结果:

flag=Bei-Jing, number=12345, name=Jone, password=ASDZXC123456
flag=Shang-Hai, number=12345, name=Jone, password=null

结果分析:

很明显,反序列化的结果中flag属性的值来自JVM,而不是文件。

 

参考文章:https://blog.csdn.net/u013207877/article/details/52572975

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jin_Kwok

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值