Java中transient关键字
Posted mico23
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中transient关键字相关的知识,希望对你有一定的参考价值。
一、概要介绍
本文要介绍的是Java中的transient关键字,transient是短暂的意思。对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。
1. 序列化
Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序列化后的对象可以被写到数据库或文件中,也可用于网络传输。一般地,当我们使用缓存cache(内存空间不够有可能会本地存储到硬盘)或远程调用rpc(网络传输)的时候,经常需要让实体类实现Serializable接口,目的就是为了让其可序列化。当然,序列化后的最终目的是为了反序列化,恢复成原先的Java对象实例。所以序列化后的字节序列都是可以恢复成Java对象的,这个过程就是反序列化。
2. 为什么要用transient关键字?
在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。
3. transient的作用
transient是Java语言的关键字,用来表示一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包括在序列化的结果中。而非transient型的变量是被包括进去的。 注意static修饰的静态变量天然就是不可序列化的。
二、transient使用总结
(1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法被访问。
(2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
(3)一个静态变量不管是否被transient修饰,均不能被序列化(如果反序列化后类中static变量还有值,则值为当前JVM中对应static变量的值)。序列化保存的是对象状态,静态变量保存的是类状态,因此序列化并不保存静态变量。
三、使用场景
(1)类中的字段值可以根据其它字段推导出来,如一个长方形类有三个属性长度、宽度、面积,面积不需要序列化。
(2) 一些安全性的信息,一般情况下是不能离开JVM的。
(3)如果类中使用了Logger实例,那么Logger实例也是不需要序列化的
为啥在java中使用`transient`关键字? [复制]
【中文标题】为啥在java中使用`transient`关键字? [复制]【英文标题】:Why use the `transient` keyword in java? [duplicate]为什么在java中使用`transient`关键字? [复制] 【发布时间】:2014-01-09 03:11:51 【问题描述】:我有一个与 transient
关键字在 java 中 private
修饰符之前的使用有关的问题。
变量声明:
transient private ResourceBundle pageResourceBundle;
我的班级是这样的:
public class LoginViewModel extends AbstractViewModel
transient private ResourceBundle pageResourceBundle;
@AfterCompose
public void afterCompose(@ContextParam(ContextType.VIEW) Component view)
initializeLoginValues();
boolean timeout = BooleanUtils.toBoolean(getHttpServletRequest().getParameter("timeout"));
if (timeout)
Messagebox.show(pageResourceBundle.getText("MSG_SESSION_HAS_EXPIRED_PLEASE_LOGIN"), pageResourceBundle.getText("LABEL_ALERT"),
Messagebox.OK, Messagebox.ERROR);
view.getPage().setTitle(CsdcLicence.get().getApplicationName());
我有一些问题。
1.为什么在私有变量前使用transient
关键字?
2.使用这个关键字的目的是什么?
【问题讨论】:
您提供的链接回答了您的两个问题。你有什么疑问?哪些内容尚未涵盖? @PeterLawrey 编辑我的问题,请查看我的课程,它没有实现序列化 您的类可能会被您正在使用的库序列化,或者transient
可能会被您与模型一起使用的库用于其他目的。它可能会在视图中显示除transient
之外的所有字段。您必须阅读您正在使用的库的文档。
有人能解释一下为什么我们要故意通过网络丢失对象吗?有什么例子吗?
【参考方案1】:
瞬态变量在 java 中从不序列化。
它标记一个成员变量,当它被持久化为字节流时,它不会被序列化。当一个对象通过网络传输时,该对象需要被“序列化”。序列化将对象状态转换为串行字节。这些字节通过网络发送,并且从这些字节重新创建对象。 java transient 关键字标记的成员变量不会被转移,它们是故意丢失的。
请看看serialization 是什么。?并参考this
例子
public class Foo implements Serializable
private String saveMe;
private transient String dontSaveMe;
private transient String password;
//...
在上面的示例中,dontSaveMe
和 password
永远不会被序列化,因为它们被声明为 transient variables
。
【讨论】:
“从不”太强了。 默认情况下它们不会序列化, 但如果您编写自己的readObject()/writeObject()
方法,您可以自己序列化它们。【参考方案2】:
还有一个简短的用例: 想象一下通过公共可用的网络服务公开一个用户对象。 您肯定想公开昵称、在线状态、电子邮件或位置等信息。 您绝对不想公开用户用于登录的密码。 虽然此密码可能是您的用户对象的属性, 它不应该被序列化,例如将对象序列化为 JSON 时 - 提到的 Web 服务的字符串。
【讨论】:
非常好的用例。我只是来找那个的。【参考方案3】:transient
关键字表明对象不应该被序列化,也不应该被持久化。如果不想序列化重物(比如Wrapper
s,可以包含很多业务逻辑),可以使用。
@Transient
注释表明对象不应该被持久化(例如,如果你一直在玩 Hibernate),但它可以被序列化。
我已经包含了注释说明,因为我记得被这两者混淆了。 :-)
【讨论】:
transient
只是关于序列化,其含义由 JLS 精确指定。 @Transient
是第 3 方定义的注解,如果没有给出完全限定的类名,它是模棱两可的。【参考方案4】:
transient
用于指定对象的哪些属性不会被保存或序列化。例如,将对象保存到文件时,transient
指定在将对象保存到文件时不会将哪些属性或属性保存到该文件。
从文件重新创建对象时,不会重新创建 transient
属性(或私有属性)的值,因为它从未保存或序列化到该文件。在某些情况下,您可能希望避免保留这些私有实例变量或对象的属性,transient
允许您这样做。
【讨论】:
以上是关于Java中transient关键字的主要内容,如果未能解决你的问题,请参考以下文章