为什么Java有瞬态字段?

1641

为什么Java有transient字段?


为了不使它们被序列化。 - user207421
15个回答

5

当您不想共享随序列化传递的某些敏感数据时,就需要它。


9
除了敏感数据之外,还有其他用例可能不需要对某个字段进行序列化。例如,您可能永远不想序列化一个 Thread(感谢 @A.H. 的例子),在这种情况下,您可以将其标记为 transient。然而,线程本身并不是敏感数据,只是没有逻辑意义进行序列化(且它不能被序列化)。 - glen3b
1
@glen3b 这个答案并没有排除那种情况。在提问者提到的情况下,这确实是必要的。 - user207421

1

transient-keyword 的简化示例代码。

import java.io.*;

class NameStore implements Serializable {
    private String firstName, lastName;
    private transient String fullName;

    public NameStore (String fName, String lName){
        this.firstName = fName;
        this.lastName = lName;
        buildFullName();
    }

    private void buildFullName() {
        // assume building fullName is compuational/memory intensive!
        this.fullName = this.firstName + " " + this.lastName;
    }

    public String toString(){
        return "First Name : " + this.firstName
            + "\nLast Name : " + this.lastName
            + "\nFull Name : " + this.fullName;
    }

    private void readObject(ObjectInputStream inputStream)
            throws IOException, ClassNotFoundException
    {
        inputStream.defaultReadObject();
        buildFullName();
    }
}

public class TransientExample{
    public static void main(String args[]) throws Exception {
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
        o.writeObject(new NameStore("Steve", "Jobs"));
        o.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
        NameStore ns = (NameStore)in.readObject();
        System.out.println(ns);
    }
}

1
因为不是所有的变量都具有可序列化的特性。
  1. 序列化和反序列化是对称的过程,如果不是这样的话,你就不能指望结果是确定的,大多数情况下,不确定的值是没有意义的;
  2. 序列化和反序列化是幂等的,这意味着你可以进行任意次数的序列化,结果都是相同的。
所以,如果对象可以存在于内存中但无法存在于磁盘上,则该对象无法被序列化,因为机器在反序列化时无法恢复内存映射。 例如,你无法序列化一个 Stream 对象。
你无法序列化一个 Connection 对象,因为它的状态也依赖于远程机器。

0

简单来说,transient Java 关键字可以保护字段不被序列化为它们的非 transient 字段副本。

在这个代码片段中,我们的抽象类 BaseJob 实现了 Serializable 接口,我们从 BaseJob 继承,但我们不需要序列化远程和本地数据源;只序列化 organizationName 和 isSynced 字段。

public abstract class BaseJob implements Serializable{
   public void ShouldRetryRun(){}
}

public class SyncOrganizationJob extends BaseJob {

   public String organizationName;
   public Boolean isSynced

   @Inject transient RemoteDataSource remoteDataSource;
   @Inject transient LocalDaoSource localDataSource;

   public SyncOrganizationJob(String organizationName) {
     super(new 
         Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());

      this.organizationName = organizationName;
      this.isSynced=isSynced;

   }
}

0
使用transient修饰符声明的字段将不参与序列化过程。 当对象被序列化(保存在任何状态中)时,其瞬态字段的值在序列化表示中被忽略,而非瞬态字段将参与序列化过程。这就是transient关键字的主要目的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接