Java transient关键字的使用,附带学习经验

然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

示例code如下:


import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;



/**

 * 使用transient关键字不序列化某个变量

 * 注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致

 */

public class TransientTest {

    static String PATH = "F:/user.txt";



    public static void main(String[] args) {



        User user = new User();

        user.setUsername("Alexia");

        user.setPasswd("123456");



        System.out.println("read before Serializable: ");

        System.out.println("username: " + user.getUsername());

        System.out.println("password: " + user.getPasswd());



        try {

            ObjectOutputStream os = new ObjectOutputStream(

                    new FileOutputStream(PATH));

            os.writeObject(user); // 将User对象写进文件

            os.flush();

            os.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

        try {

            ObjectInputStream is =

                    new ObjectInputStream(new FileInputStream(PATH));

            user = (User) is.readObject(); // 从流中读取User的数据

            is.close();



            System.out.println("\nread after Serializable: ");

            System.out.println("username: " + user.getUsername());

            System.out.println("password: " + user.getPasswd());



        } catch (ClassNotFoundException | IOException e) {

            e.printStackTrace();

        }

    }

}



class User implements Serializable {

    private static final long serialVersionUID = 8294180014912103005L;  



    private String username;

    private transient String passwd;



    public String getUsername() {

        return username;

    }



    public void setUsername(String username) {

        this.username = username;

    }



    public String getPasswd() {

        return passwd;

    }



    public void setPasswd(String passwd) {

        this.passwd = passwd;

    }

}

输出结果:

Java transient关键字的使用,附带学习经验

密码字段为null,说明反序列化时根本没有从文件中获取到信息。

2. transient使用小结

1)被transient关键字修饰的变量不能被序列化,变量将不再是对象持久化的一部分,该变量内容在序列化后无法通过反序列化获得。

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)一个静态变量不管是否被transient修饰,均不能被序列化。

第三点可能有些人很迷惑,因为发现在User类中的username字段前加上static关键字后,程序运行结果依然不变,即static类型的username也读出来为“Alexia”了,这不与第三点说的矛盾吗?实际上是这样的:第三点确实没错(一个静态变量不管是否被transient修饰,均不能被序列化),反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的,不相信?好吧,下面我来证明:


import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;



public class TransientTest {

    static String PATH = "F:/user.txt";



    public static void main(String[] args) {



        User user = new User();

        user.setUsername("Alexia");

        user.setPasswd("123456");



        System.out.println("read before Serializable: ");

        System.out.println("username: " + user.getUsername());

        System.out.println("password: " + user.getPasswd());



        try {

            ObjectOutputStream os = new ObjectOutputStream(

                    new FileOutputStream(PATH));

            os.writeObject(user); // 将User对象写进文件

            os.flush();

            os.close();

        } catch (IOException e) {

            e.printStackTrace();

        }



        try {

            // 在反序列化之前改变username的值

            User.username = "jmwang";



            ObjectInputStream is =

                    new ObjectInputStream(new FileInputStream(PATH));

            user = (User) is.readObject(); // 从流中读取User的数据

            is.close();



            System.out.println("\nread after Serializable: ");

            System.out.println("username: " + user.getUsername());

            System.out.println("password: " + user.getPasswd());



        } catch (ClassNotFoundException | IOException e) {

            e.printStackTrace();

        }

    }

}



class User implements Serializable {

    private static final long serialVersionUID = 8294180014912103005L;  



    public static String username;

    private transient String passwd;



    public String getUsername() {

        return username;

    }



    public void setUsername(String username) {

        this.username = username;

    }



    public String getPasswd() {
#### 总结

这次面试问的还是还是有难度的,要求当场写代码并且运行,也是很考察面试者写代码
因为Android知识体系比较庞大和复杂的,涉及到计算机知识领域的方方面面。**在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。**

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
![](https://www.icode9.com/i/ll/?i=img_convert/4751e4d1c7abe41f7e66927ee4fbee1c.png)
**里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**

**[CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://codechina.csdn.net/m0_60958482/android_p7)**

集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中...(img-RwD6bWFE-1630668388192)]
**里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**

**[CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://codechina.csdn.net/m0_60958482/android_p7)**

上一篇:Java transient关键字的使用,Java开发者跳槽面试


下一篇:transient关键字