Java中的transient关键字解析

 更新时间:2023年09月28日 09:12:58   作者:光与热  
这篇文章主要介绍了Java中的 transient关键字解析,有时候我们的一些敏感信息比如密码并不想序列化传输给对方,这个时候transient关键字就派上用场了,如果一个类的变量加上了transient关键字那么这个字段就不会被序列化,需要的朋友可以参考下

transient关键字

java对象在实现了Serilizable接口后这个对象就可以被序列化,但是java的这种序列化机制会将这个类的所有属性和方法都序列化.有时候我们的一些敏感信息比如密码并不想序列化传输给对方,这个时候transient关键字就派上用场了,如果一个类的变量加上了transient关键字那么这个字段就不会被序列化

下面这个例子我们利用transient避免User序列化过程中密码字段的序列化

@Data
@ToString
@AllArgsConstructor
public class User implements Serializable {
    private String username;
    private transient String password;
}

我们首先创建一个对象User,利用ObjectOutputStream序列化到本地文件,利用ObjectInputStream读取并反序列化为User对象

try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("user.txt"));
     ObjectInputStream is = new ObjectInputStream(new FileInputStream("user.txt"));) {
    User user = new User("jack", "123456");
    System.out.println(user);
    os.writeObject(user);
    os.flush();
    user = (User) is.readObject();
    System.out.println(user);
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

运行结果如下

User{username='jack', password='123456'}
User{username='jack', password='null'}

可以看到密码字段为空

从上面这个例子可以看到一旦变量被transient关键字修饰,该变量就不参与持久化过程,再进一步深入学习transient

1. transient关键字只能修饰变量,不能修饰方法和类.如果变量类型是我们自定义的类,那么这个类需要实现Serializable接口

2. 静态变量无论是否被transient关键字修饰都不参与序列化

接下来我们详细讲解下上述的第二点 我们给User添加一个字段Country,这是一个静态字段

我们重试上面的过程

try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("user.txt"));
     ObjectInputStream is = new ObjectInputStream(new FileInputStream("user.txt"));) {
    User user = new User("jack", "123456");
    User.setCountry("China");
    System.out.println(user);
    os.writeObject(user);
    os.flush();
    user = (User) is.readObject();
    System.out.println(user);
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

与第一个例子不同点在于我们在利用setter设置Country

运行结果

User{username='jack', password='123456', country='China'}
User{username='jack', password='null', country='China'}

我们发现country好像被序列化了,但是静态变量无论如何都不参与初始化的,我们猜想country中的值是jvm中的而不是反序列化出来的 我们利用下面这个例子验证我们的猜想

try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("user.txt"));
     ObjectInputStream is = new ObjectInputStream(new FileInputStream("user.txt"));) {
    User user = new User("jack", "123456");
    User.setCountry("China");
    System.out.println(user);
    os.writeObject(user);
    os.flush();
    User.setCountry("American");
    user = (User) is.readObject();
    System.out.println(user);
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

对象序列化写入文件后我们再修改User的country字段为American

结果如下

User{username='jack', password='123456', country='China'}
User{username='jack', password='null', country='American'}

可以看到country果然变成了American我们的猜想成立,也就是说反序列化后static型变量的值为JVM中的值

还有一点关于transient关键字失灵的情况需要注意,看下面这个例子

@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Externalizable {
    private transient String username;
    private transient int age;
    private transient String fatherName;
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(username);
        out.writeInt(age);
        out.writeObject(fatherName);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        username = (String) in.readObject();
        age = in.readInt();
        fatherName= (String) in.readObject();
    }
}

student学生类实现了Externalizable接口作用我们下面再讲,student的所有属性都使用transient关键字修饰

测试代码如下

try (ObjectInput in = new ObjectInputStream(new FileInputStream(new File("student.txt")));
     ObjectOutput out = new ObjectOutputStream(new FileOutputStream(new File("student.txt")));) {
    Student student = new Student("student", 20, "father");
    System.out.println(student);
    out.writeObject(student);
    out.flush();
    student = (Student) in.readObject();
    System.out.println(student);
} catch (Exception e) {
    e.printStackTrace();
}

运行结果如下所示

Student(username=student, age=20, fatherName=father)
Student(username=student, age=20, fatherName=father)

可以看到尽管transient关键字修饰了所有属性,按理这些属性都不应该被序列化,这是为什么呢,这要谈到java的序列化机制了,java自带的对象的序列化可以通过两种方法实现,一种就是Serializable,另外一种就是上面的Externalizable,利用External自定义java序列化方式,选择序列化哪些属性都与transient关键字无关了

到此这篇关于Java中的transient关键字解析的文章就介绍到这了,更多相关Java中的 transient内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用IDEA搭建MyBatis环境详细过程

    使用IDEA搭建MyBatis环境详细过程

    这篇文章主要介绍了使用IDEA搭建MyBatis环境的相关知识,包括创建项目的过程及导入mybatis的核心jar包的详细说明,本文通过图文实例代码相结合给大家介绍的非常详细,需要的朋友可以参考下
    2021-05-05
  • Java CAS基本实现原理代码实例解析

    Java CAS基本实现原理代码实例解析

    这篇文章主要介绍了Java CAS基本实现原理代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Java 静态数据初始化的示例代码

    Java 静态数据初始化的示例代码

    这篇文章主要介绍了Java 静态数据初始化的示例代码,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • SpringBoot 项目如何在tomcat容器中运行的实现方法

    SpringBoot 项目如何在tomcat容器中运行的实现方法

    这篇文章主要介绍了SpringBoot 项目如何在tomcat容器中运行的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Spring Boot 工程的创建和运行(图文)

    Spring Boot 工程的创建和运行(图文)

    这篇文章主要介绍了Spring Boot 工程的创建和运行(图文),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • 关于Java反编译字节码文件

    关于Java反编译字节码文件

    将高级语言翻译成汇编语言或机器语言的过程Java语言中的编译一般指将Java文件转换成class文件顾名思义反编译就是编译的逆向过程其实我们常用的开发工具(例如:IDEA、Eclipse)都带有反编译功能,需要的朋友可以参考下
    2023-05-05
  • Linux下Java环境变量的安装与配置

    Linux下Java环境变量的安装与配置

    这篇文章给大家介绍了Linux下Java环境变量的安装与配置,本文以jdk1.6.0_43为例,给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-07-07
  • ruoyi-springboot框架新增模块调接口报404的解决方案

    ruoyi-springboot框架新增模块调接口报404的解决方案

    这篇文章主要介绍了ruoyi-springboot框架新增模块调接口报404的解决方案,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-03-03
  • SpringBoot各种参数校验的实例教程

    SpringBoot各种参数校验的实例教程

    经常需要提供接口与用户交互(获取数据、上传数据等),由于这个过程需要用户进行相关的操作,为了避免出现一些错误的数据等,一般需要对数据进行校验,下面这篇文章主要给大家介绍了关于SpringBoot各种参数校验的相关资料,需要的朋友可以参考下
    2022-03-03
  • SpringBoot整合FastDFS中间件实现文件分布管理

    SpringBoot整合FastDFS中间件实现文件分布管理

    FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件上传、文件下载等,解决了大容量存储和负载均衡的问题,本文介绍了SpringBoot整合FastDFS中间件实现文件分布管理,需要的朋友可以参考下
    2024-08-08

最新评论