前往小程序,Get更优阅读体验!
立即前往
社区首页 >专栏 >面试官:transient关键字修饰的变量当真不可序列化?我:烦请先生教我!

面试官:transient关键字修饰的变量当真不可序列化?我:烦请先生教我!

原创
作者头像
JavaBuild
发布于 2024-06-27 07:09:08
发布于 2024-06-27 07:09:08
940
举报
文章被收录于专栏:Java成长计划Java成长计划

一、写在开头

在这篇文章中记录一下之前自己面试时学到的东西,是关于transient关键字的,当时面试官问我IO的相关问题,基本上全答出来了,关于如何不序列化对象中某个字段时,我果断的选择了static和transient,但面试官紧接着问了我:“transient关键字修饰的变量当真不可序列化吗?”,这个问题直接给我整不确定了,因为以当时的知识储备,这个问题确实不知道,最终虚心的向这位面试官请教,他告诉了我答案。

虽然那场面试我还是通过了,但是我没去,哈哈!不过还是挺感谢那个耐心的面试官的,随口的一个问题,其实大部分面试官是不会负责给你解答的。

二、案例测试

今天,我们就花一点时间,来把这个问题梳理一遍。我们先写一个测试类,去看一下static和transient关键字修饰的字段,在序列化过程中的表现:

代码语言:java
复制
public class Test {
    public static void main(String[] args) throws IOException {
        //初始化对象信息
        Person person = new Person();
        person.setName("JavaBuild");
        person.setAge(30);
        System.out.println(person.getName()+" "+person.getAge());

        //序列化过程
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("E:\\person.txt"));) {
            objectOutputStream.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }
        person.par1 = "序列化后静态字段";
        //反序列化过程
        try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\person.txt"));) {
            Person p = (Person) objectInputStream.readObject();
            System.out.println(p);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}
class Person implements Serializable{

    private static final long serialVersionUID = 8711922740433840551L;
    private String name;
    private int age;

    public static String par1 = "静态字段";
    transient String par2 = "临时字段";
    transient int high = 175;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", par1=" + par1 +
                ", high=" + high +
                ", par2='" + par2 + '\'' +
                '}';
    }
}

输出:

代码语言:java
复制
JavaBuild 30
Person{name='JavaBuild', age=30, par1=序列化后静态字段, high=0, par2='null'}

通过打印结果我们可以看到,static修饰的字段,并没有参与序列化,读取到了后面修改的值;transient关键字修饰的字段也没参与,而且在反序列化过程中,会被重置为默认值,例如基本数据类型为 0,引用类型为 null。至于原因我们在这里不展开了,上一篇文章里已经提到,大家可以去看看。

三、直入主题

我们再回过头来看看起初的问题:transient 修饰的字段真的不能被序列化?

至少通过Serializable接口标示的序列化方式里,transient字段时不可被序列化的,因为在序列化过程中调用的ObjectStreamClass对象,里面有个方法为getDefaultSerialFields(),已经明确的标记出了transient修饰符不可被序列化!

那我们怎么办呢?

Externalizable接口:

其实呀,除了 Serializable 之外,Java 还提供了一个序列化接口 Externalizable,它是Serializable的子接口,使用 Externalizable 进行反序列化的时候,会调用被序列化类的无参构造方法去创建一个新的对象,然后再将被保存对象的字段值复制过去;实现Externalizable接口时,必须重写其中的writeExternal() 和 readExternal()方法,我们通过这两个方法进行序列化的设计与读取。

适应场景: 因为Externalizable接口拥有着更高的序列化控制能力,所以在序列化过程中,我们需要对一些敏感信息进行加密处理时,它的作用就会体现啦。

我们使用这个接口进行序列化尝试,并且使用transient关键字修饰字段,看一下结果:

代码语言:java
复制
public class Test implements Externalizable {

    private transient String text = "我可以被序列化!!!";

    public static void main(String[] args) throws Exception {
        Test test = new Test();
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("E:\\transient.txt"));
        out.writeObject(test);
        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("E:\\transient.txt"));
        test = (Test)in.readObject();
        System.out.println(test.text);
        //关闭流
        out.close();
        in.close();
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(text);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        text = (String) in.readObject();
    }
}

输出:

代码语言:java
复制
我可以被序列化!!!

数据成功被序列化到txt文件中,并成功的反序列化读取到程序中了!即便text被transient修饰着!

四、总结

通过上面的学习,我们知道了在Java的序列化中有 Serializable、Externalizable这两个接口,前者没有任何方法,只是一个标识,而后者作为子类,提供了必须重写的方法,用以自定义序列化设计。此外,transient 关键字只能修饰字段,而不能修饰方法和类,需要注意。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
当时给的回答是:不想被序列化的变量我们可以使用transient或static关键字修饰;transient 关键字的作用是阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复;而static关键字修饰的变量并不属于对象本身,所以也同样不会被序列化!
JavaBuild
2024/06/23
1990
面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
Java transient关键字的理解
我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
翎野君
2023/05/12
2410
Java transient关键字的理解
transient关键字
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说transient关键字,希望能够帮助大家进步!!!
Java架构师必看
2022/01/12
4420
Java transient关键字使用小记
1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列
Spark学习技巧
2018/03/20
8560
Java transient关键字
transient关键字是开发中用的比较少的一个关键字,它在序列化和反序列化中比较重要,通常面试时会考察它的作用和它的使用场景,还有它在什么情况下会失效。
PhoenixZheng
2018/08/07
1.8K0
transient关键字的作用是什么?
我们知道,如果一个对象需要序列化,那么需要实现Serilizable接口,那么这个类的所有非静态属性,都会被序列化。
秦怀杂货店
2020/11/22
7740
transient关键字的作用是什么?
面试官:说说你对序列化的理解
在Java语言中,程序运行的时候,会产生很多对象,而对象信息也只是在程序运行的时候才在内存中保持其状态,一旦程序停止,内存释放,对象也就不存在了。
田维常
2020/12/14
3780
Java transient关键字解析
最近在看hsweb-framework项目,看到了对象属性有用transient关键字修饰,工作两年的我一脸懵逼,特意查阅了一下这个修饰符的意思,并记录下来!
java干货
2021/02/17
4990
序列化机制深入了解 | Java
序列化是将对象保存在磁盘中,或允许在网络中直接传输对象。对象序列化机制允许把内存中的java对象转成与平台无关的二进制流,从而将这种二进制文件持久的保存在磁盘上。其他程序一旦获得了这种二进制的流。就可以将这个二进制流恢复成原来的java对象
345
2022/02/11
2660
Java 序列化
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。
HLee
2021/05/08
1.2K0
Java 序列化
关于Java序列化的问题你真的会吗?
在持久化数据对象的时候我们很少使用Java序列化,而是使用数据库等方式来实现。但是在我看来,Java 序列化是一个很重要的内容,序列化不仅可以保存对象到磁盘进行持久化,还可以通过网络传输。在平时的面试当中,序列化也是经常被谈及的一块内容。
宜信技术学院
2020/03/11
4380
Java中的transient关键字
概述 在Java中,一个类只要实现Serializable接口,这个类的对象就可以被序列化,这种序列化模式为开发者提供了很多便利,我们可以不必关心具体序列化的过程,只要这个类实现了Serializable接口,这个类的所有属性都会自动序列化。但是有时我们需要让类的某些属性不被序列化,如密码这类信息,为了安全起见,不希望在网络操作中被传输或者持久化到本地。只要在相应的属性前加上 transient关键字,就可以实现部分属性不被序列化,该属性的生命周期仅存于调用者的内存中而不会写入到磁盘持久化。 transie
用户1205080
2018/12/25
4540
Java 序列化
被序列化的类必须属于 Enum、Array 和 Serializable 类型其中的任何一种。
静默虚空
2018/07/31
5290
Java 序列化
Java序列化和反序列化
Java序列化(Serialize)是指将一个Java对象写入IO流中; Java反序列化(Deserialize)指的是从IO流中回复IO对象。
悠扬前奏
2019/05/28
8840
Java 序列化与反序列化
1、什么是序列化?为什么要序列化?     Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程。     我们都知道,在进行浏览器访问的时候,我们看到的文本、图片、音频、视频等都是通过二进制序列进行传输的,那么如果我们需要将Java对象进行传输的时候,是不是也应该先将对象进行序列化?答案是肯定的,我们需要先将Java对象进行序列化,然后通过网络,IO进行传输,当到达目的地之后,再进行反序列化获取到我们想要的对象,最后完成通信。 2、如何实现序列化 2.1、使用
九灵
2018/03/09
1.3K0
IO流的序列化和反序列化
不知道你们看到这句话的时候,有没有感到疑惑?嘿嘿,那就对了,这个你们可能没去了解过。
JanYork_简昀
2022/04/15
4860
IO流的序列化和反序列化
java序列化学习笔记
概念 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。 这两个过程结合起来,可以轻松地存储和传输数据。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 目的 1、以某种存储形式使自定义对象持久化,在MVC模式中很是有用; 2、将对象从一个地方传递到另一个地方; 实现方法 实现 java.io.Serializable 接口 序列化时,需要用到对象输出流ObjectOutputStream ,然后通过文件输出流构造 ObjectOutputStr
张俊怡
2018/04/24
8320
简述java序列化
1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。 使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。 除了在持久化对象时会用到对象序列化之外,当使用RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。Java序列化API为处理对象序列化提供了一个标准机制,该API简单易用,在本文的后续章节中将会陆续讲到。 2. 简单示例 在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。此处将创建一个可序列化的类Person,本文中的所有示例将围绕着该类或其修改版。 Gender类,是一个枚举类型,表示性别
WindWant
2020/09/11
4490
关于序列化/反序列化,我梭哈
光看定义上,对于初学者来说,可能很难一下子理解序列化的意义,尤其是面对这种特别学术词语的时候,内心会不由自主的发问:它到底是啥,用来干嘛的?
Java极客技术
2022/12/02
4600
小伙子,你真的搞懂 transient 关键字了吗?
我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术。
Java技术栈
2019/05/07
4100
小伙子,你真的搞懂 transient  关键字了吗?
相关推荐
面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文