transient关键字解读笔记

本文围绕Java的transient关键字展开。介绍其用途,即修饰的属性在对象序列化时不被序列化,反序列化用默认值。还说明了使用方法,在属性前添加该关键字。此外,探讨了它与static、final关键字结合的效果,最后总结了使用注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在阅读ArrayList源码时,发现一个以前没有遇到过的关键字transient,于事百度了一下,百度到这篇博客 transient关键字详解,作者讲得很详细,我也对transient关键字有了一定的了解,所以我自己也整理一下,一是加强理解,二是便于自己以后直接查看。

1. transient关键字的用途

首先我们需要知道,当一个对象实现了Serializable接口后,该对象就可以被序列化(一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序)。并且,该对象的所有属性和方法都会被自动序列化。而在开发过程中,遇到不希望序列化某些属性(包含敏感信息的属性)的需求时,这时就需要transient关键字了。所以,transient的用途:
一个对象实例被transient修饰的属性在其序列化的过程中不会被序列化(或者说变量持久化),执行序列化时,JVM会忽略transient变量的原始值并将默认值保存到文件中。并且,当该对象实例被反序列化时:被transient修饰的属性的值不会被恢复,而且使用默认值来表示。

2. 使用方法

在不希望序列化的属性前添加transient关键字即可。
示例:

package com.fuqi.transientlean;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

/**
 * @Description: User实体类
 * @Author 傅琦
 * @Date 2019/5/29 21:56
 * @Version V1.0
 */
@AllArgsConstructor
@Data
public class User implements Serializable {
    private static final long serialVersionUID = 8645066796013228213L;
    private String username;
    private int age;
    private transient String password;
}

这里我在工程中添加了Lombok依赖,并且在IDE中安装了Lombok的插件(具体安装方式可直接百度),所以可以直接通过注解来生成一个实体类的构造方法、getter()、setter()、hashCode()、toString()方法等常见方法。

测试方法:

package com.fuqi.transientlean;

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

/**
 * @Description: 测试transient关键字的作用
 * @Author 傅琦
 * @Date 2019/5/29 22:02
 * @Version V1.0
 */
public class TestTransient {
    public static void main(String[] args){
        // 初始化一个对象
        User user = new User("李雷", 20, "lilei123");
        System.out.println(user);
        // 将对象进行序列化
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.txt"));
            oos.writeObject(user);
            oos.close();
        }catch (Exception e){
            e.printStackTrace();
        }

        // 反序列化对象
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));
            User userRead = (User) ois.readObject();
            System.out.println(userRead);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

测试结果截图:
在这里插入图片描述
上图中密码字段反序列化出来值为null,说明被transient修饰的属性不会被序列化,保存不到磁盘中,反序列化时也就取不出原来的值,只能使用默认值。

Transient 与 Static

当被修饰的变量同时也被static关键字所修饰时,会是什么效果呢?
这里我新建了一个Male类来测试

package com.fuqi.transientlean;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

/**
 * @Description: Male实体类
 * @Author 傅琦
 * @Date 2019/5/29 22:12
 * @Version V1.0
 */
@AllArgsConstructor
@Data
public class Male implements Serializable {
    private static final long serialVersionUID = 405573135826470637L;
    private transient static String name = "李雷";
    private int age;
    private transient int salary;

    public static String getName() {
        return name;
    }

    public static void setName(String name) {
        Male.name = name;
    }
}

上面的代码中,name属性同时被transient和static关键字所修饰,现在对其进行简单的测试:

package com.fuqi.transientlean;

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

/**
 * @Description: 测试transient关键字的作用
 * @Author 傅琦
 * @Date 2019/5/29 22:02
 * @Version V1.0
 */
public class TestTransient {
    public static void main1(String[] args){
        // 初始化一个对象
        User user = new User("李雷", 20, "lilei123");
        System.out.println(user);
        // 将对象进行序列化
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.txt"));
            oos.writeObject(user);
            oos.close();
        }catch (Exception e){
            e.printStackTrace();
        }

        // 反序列化对象
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));
            User userRead = (User) ois.readObject();
            System.out.println(userRead);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        Male male = new Male(15, 25000);
        System.out.println(Male.getName() + ": " + male);
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("male.txt"));
            oos.writeObject(male);
            oos.close();
        }catch (Exception e){
            e.printStackTrace();
        }

        // 反序列化对象
        try {
        	// 反序列化之前修改name属性的值
            Male.setName("韩梅梅");
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("male.txt"));
            Male maleRead = (Male) ois.readObject();
            System.out.println(Male.getName() + ": " + maleRead);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这里将上次的测试方法改一下方法命,再新写一个main方法来测试,测试结果如下图:
在这里插入图片描述
从上图中可以看到,name属性并不为null,反而是有值的。原因何在?
这是因为:
static关键字修饰的属性,也叫静态变量,静态变量不是对象状态的一部分,因此它不参与序列化。所以将静态变量声明为transient变量是没有用处的。因此,反序列化后类中static型变量name的值实际上是当前JVM中对应static变量的值,这个值是JVM中的并不是反序列化得出的。

Final 与 Transient

对Male代码稍作修改,再直接测试:

package com.fuqi.transientlean;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

/**
 * @Description: Male实体类
 * @Author 傅琦
 * @Date 2019/5/29 22:12
 * @Version V1.0
 */
@AllArgsConstructor
@Data
public class Male implements Serializable {
    private static final long serialVersionUID = 405573135826470637L;
    private transient static String name = "李雷";
    private int age;
    private transient int salary;
    // 加一个final关键字修饰的属性
    private final transient String description = "男";

    public static String getName() {
        return name;
    }

    public static void setName(String name) {
        Male.name = name;
    }
}

测试方法直接使用前面测试static关键字的方法,其结果为:
在这里插入图片描述
上图的结果说明final变量声明为transient变量不会产生任何影响

3. 小结

  1. 一旦一个变量被transient修饰,该变量将不再是对象持久化的一部分,该变量的内容在序列化后无法在访问到。
  2. transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
  3. 被static关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
  4. 被final关键字修饰的变量不会被transient关键字所影响,是可以正常序列化的,final变量将直接通过值参与序列化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值