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;
  //...

在上面的示例中,dontSaveMepassword 永远不会被序列化,因为它们被声明为 transient variables

【讨论】:

“从不”太强了。 默认情况下它们不会序列化, 但如果您编写自己的 readObject()/writeObject() 方法,您可以自己序列化它们。【参考方案2】:

还有一个简短的用例: 想象一下通过公共可用的网络服务公开一个用户对象。 您肯定想公开昵称、在线状态、电子邮件或位置等信息。 您绝对不想公开用户用于登录的密码。 虽然此密码可能是您的用户对象的属性, 它不应该被序列化,例如将对象序列化为 JSON 时 - 提到的 Web 服务的字符串。

【讨论】:

非常好的用例。我只是来找那个的。【参考方案3】:

transient 关键字表明对象不应该被序列化也不应该被持久化。如果不想序列化重物(比如Wrappers,可以包含很多业务逻辑),可以使用。

@Transient 注释表明对象不应该被持久化(例如,如果你一直在玩 Hibernate),但它可以被序列化

我已经包含了注释说明,因为我记得被这两者混淆了。 :-)

【讨论】:

transient 只是关于序列化,其含义由 JLS 精确指定。 @Transient 是第 3 方定义的注解,如果没有给出完全限定的类名,它是模棱两可的。【参考方案4】:

transient 用于指定对象的哪些属性不会被保存或序列化。例如,将对象保存到文件时,transient 指定在将对象保存到文件时不会将哪些属性或属性保存到该文件。

从文件重新创建对象时,不会重新创建 transient 属性(或私有属性)的值,因为它从未保存或序列化到该文件。在某些情况下,您可能希望避免保留这些私有实例变量或对象的属性,transient 允许您这样做。

【讨论】:

以上是关于Java中transient关键字的主要内容,如果未能解决你的问题,请参考以下文章

Java中transient关键字的详细总结

Java中transient关键字的详细总结

transient-java 关键字

Java 中关键字transient引出序列化与反序列化

JAVA中TRANSIENT关键字的作用

java中的transient关键字详解