JAVA语言-transient用途及序列化的使用方法
周鸣君 2018-04-04 来源 : 阅读 1640 评论 1

摘要:在JAVA语言中,transient当一个对象实现了Serilizable接口,这个对象就可以被序列化,我们不关心其内在的原理,只需要了解这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。序列化的时候,将不需要序列化的属性前添加关键字transient即可。学会这些让我们对JAVA语言有了更深刻的认识。

transient的用途及使用方法

1,用途

  我们知道,当一个对象实现了Serilizable接口,这个对象就可以被序列化,我们不关心其内在的原理,只需要了解这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。而在开发过程中,我们可能要求:当对象被序列化时(写入字节序列到目标文件)时,有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。 
 所以,transient的用途在于:阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为java.io.InputStream的变量,序列化时这些变量引用的输入流无法被打开。

2,使用方法

序列化的时候,将不需要序列化的属性前添加关键字transient即可。 
示例:

package newDay.day13;
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;
 
class UserInfo implements Serializable {  
    private static final long serialVersionUID = 996890129747019948L;  
    private String name;  
    private transient String psw;  
 
    public UserInfo(String name, String psw) {  
        this.name = name;  
        this.psw = psw;  
    }  
 
    public String toString() {  
        return "name=" + name + ", psw=" + psw;  
    }  
}  public class TestTransient {
    public static void main(String[] args) {  
        UserInfo userInfo = new UserInfo("张三", "123456");  
        System.out.println(userInfo);  
        try {  
            // 序列化,被设置为transient的属性没有被序列化  
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));  
            o.writeObject(userInfo);  
            o.close();  
        } catch (Exception e) {  
            // TODO: handle exception  
            e.printStackTrace();  
        }  
        try {  
            // 重新读取内容  
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));  
            UserInfo readUserInfo = (UserInfo) in.readObject();  
            //读取后psw的内容为null  
            System.out.println(readUserInfo.toString());  
        } catch (Exception e) {  
            // TODO: handle exception  
            e.printStackTrace();  
        }  
    }  
}

运行结果:

 name=张三, psw=123456name=张三, psw=null

密码字段为null,说明被标记为transient的属性在对象被序列化的时候不会被保存。

使用小结:

  1,一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 
  2,transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。 
  3,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 
  对于第三点,加上static之后,依然能把姓名输出。这是因为:反序列化后类中static型变量name的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。下例可说明,其值时JVM中得到的而不是反序列化得到的:

package newDay.day13;
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;
 
class UserInfo implements Serializable {  
    private static final long serialVersionUID = 996890129747019948L;  
    private static String name;  
    private transient String psw;  
 
    public UserInfo(String name, String psw) {  
        this.name = name;  
        this.psw = psw;  
    }  
 
    public static String getName() {
        return name;
    }
 
    public static void setName(String name) {
        UserInfo.name = name;
    }
 
    public String getPsw() {
        return psw;
    }
 
    public void setPsw(String psw) {
        this.psw = psw;
    }
 
    public String toString() {  
        return "name=" + name + ", psw=" + psw;  
    }  
}  public class TestTransient {
    public static void main(String[] args) {  
        UserInfo userInfo = new UserInfo("张三", "123456");
        System.out.println(userInfo);  
        try {  
            // 序列化,被设置为transient的属性没有被序列化  
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));  
            o.writeObject(userInfo);  
            o.close();  
        } catch (Exception e) {  
            // TODO: handle exception  
            e.printStackTrace();  
        }  
        try {  
            //在反序列化之前改变name的值
            userInfo.setName("hello");
            // 重新读取内容  
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));  
            UserInfo readUserInfo = (UserInfo) in.readObject();  
            //读取后psw的内容为null  
            System.out.println(readUserInfo.toString());  
        } catch (Exception e) {  
            // TODO: handle exception  
            e.printStackTrace();  
        }  
    }  
}

运行结果:

name=张三, psw=123456name=hello, psw=null

这说明反序列化后类中static型变量name的值为当前JVM中对应static变量的值,为修改后hello,而不是序列化时的值“张三”

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言JAVA频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(1)
后参与评论
金义飞翔
周老师讲课很幽默,很风趣,听起来很容易理解
2018/07/10 20:27:25
本文作者 联系TA

擅长Hadoop/Spark大数据技术

  • 10
    文章
  • 5496
    人气
  • 87%
    受欢迎度

已有15人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
JAVA语言-java中的字符串
经验技巧 100% 的用户喜欢
JAVA语言-Object类的equals方法和hashCode方法
经验技巧 100% 的用户喜欢
JAVA语言——网络编程、反射
经验技巧 0% 的用户喜欢
JAVA从入门到精通-java中array的常用操作
经验技巧 0% 的用户喜欢
JAVA语言-Java中jstat的用法
经验技巧 0% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
程光淼
程光淼 联系TA
精通C、C++等语言、智能芯片开发
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程