transient关键字和序列化的关系

本文详细解析了Java中transient关键字的作用及其应用场景,特别是在序列化过程中的表现。文章通过实例演示了transient如何影响实例变量、静态变量及集合类型的序列化行为,并解释了为何某些情况下需要避免默认序列化。

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

1.transient修饰实例变量

  • 类序列化时,数组 or 集合类型均被保存为null;
  • 类序列化时,基本类型也不保存其值;
  • 反序列化时,基本类型会由JVM为其赋初值,比如int类型赋值为0。

说明:序列化时,即使实例变量的值并未保存,但是域还是存在的,只是域指向为空指针

2.static变量

  • 序列化时,值会被保存。

3.transient存在意义:

  • 业务需要,不适合序列化一些字段值,比如银行密码;
  • 更重要的是:有时候默认的序列化方式不适合,所以这时候不采用默认的序列化,而是自己去定义序列化形式。
    • 比如hashMap中对元素的存储。java 7中hashMap元素的存储结构为 表 (table)+ 链(结点构成的链)的存储结构。其中根据hash(key)求的对应元素在table的索引,并将元素插入此索引处的链表。那么显然源码中对table使用了transient,故序列化时,table是不会存储值的,为什么这么设计?
    • 原因:不是不序列化,而是不采用默认的序列化。由于table中元素信息是我们存取关注的,而非table的结构,所以能合理的完成table中所有信息的存取是关键。鉴于table结构过于复杂(其中的链表结构为Entry 结点构成的链表),若采用默认的序列化方式,会将table的完整结构(包括各链表)镜像一份,如此以来带来一下弊端:
      • 需要消化大量时间遍历table结构
      • 占用较多的存储空间
      • 默认序列化对对象图做递归遍历当表过大时会发生堆栈溢出,所以避免使用默认的序列化方式。

4.代码测试:

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

class Test implements Serializable{
    private static final long serialVersionUID = 99689012974701994L;
    transient int num1;
    static int num2;
    int num3;
    transient int[] arrays={1,2,3};
    transient ArrayList<Integer> list=new ArrayList<>();
    transient HashSet<Integer> set=new HashSet<>();
    transient HashMap<Integer,Integer> map=new HashMap<>();

    Test(int n1,int n2,int n3){
        this.num1=n1;
        this.num2=n2;
        this.num3=n3;
        list.add(1);
        set.add(2);
        map.put(1,2);
    }
    private void get(){
        System.out.println("1111");
    }
}

public class Main {
    public static void main(String[] args) {
    //Scanner scanner = new Scanner(System.in);在线笔试

    //序列化
    try{
        Test test=new Test(1,2,3);
        ObjectOutputStream o=new ObjectOutputStream(new FileOutputStream("/Users/caoxiaohong/Downloads/test.txt"));
        o.writeObject(test);
        o.close();
    }catch (Exception e){
        e.printStackTrace();
    }
    //反序列化
    try{
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("/Users/caoxiaohong/Downloads/test.txt"));
        Test readIn=(Test)in.readObject();
        System.out.println("Test.num1="+readIn.num1);
        System.out.println("Test.num2="+readIn.num2);
        System.out.println("Test.num3="+readIn.num3);
        if(readIn.arrays==null){
            System.out.println("Test.arrays is null");
        }else{
            System.out.println("Test.arrays.length="+readIn.arrays.length);
        }
        if(readIn.list==null){
            System.out.println("Test.list is null");
        }else{
            System.out.println("Test.list.size()="+readIn.list.size());
        }
        if(readIn.set==null){
            System.out.println("Test.set is null");
        }else{
            System.out.println("Test.set.size()="+readIn.set.size());
        }
        if(readIn.map==null){
            System.out.println("Test.map is null");
        }else{
            System.out.println("Test.map.size()="+readIn.map.size());
        }
    }catch (Exception e){
        e.printStackTrace();
    }
    }
}

输出结果:

Test.num1=0
Test.num2=2
Test.num3=3
Test.arrays is null
Test.list is null
Test.set is null
Test.map is null
Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值