为什么Java有瞬态字段?

问题描述 投票:1345回答:13

为什么Java有瞬态字段?

java field transient
13个回答
1590
投票

Java中的transient关键字用于指示字段不应该是序列化(这意味着保存,比如文件)过程的一部分。

来自Java Language Specification, Java SE 7 EditionSection 8.3.1.3. transient Fields

可以将变量标记为transient以指示它们不是对象的持久状态的一部分。

例如,您可能具有从其他字段派生的字段,并且只应以编程方式执行,而不是通过序列化保持状态。

这是一个GalleryImage类,其中包含图像和从图像派生的缩略图:

class GalleryImage implements Serializable
{
    private Image image;
    private transient Image thumbnailImage;

    private void generateThumbnail()
    {
        // Generate thumbnail.
    }

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

在此示例中,thumbnailImage是通过调用generateThumbnail方法生成的缩略图图像。

thumbnailImage字段标记为transient,因此只有原始的image被序列化而不是保持原始图像和缩略图图像。这意味着保存序列化对象所需的存储空间更少。 (当然,根据系统的要求,这可能是也可能不合适 - 这只是一个例子。)

在反序列化时,调用readObject方法以执行将对象的状态恢复回序列化发生状态所需的任何操作。这里需要生成缩略图,因此会覆盖readObject方法,以便通过调用generateThumbnail方法生成缩略图。

有关其他信息,Discover the secrets of the Java Serialization API文章(最初在Sun Developer Network上提供)有一节讨论使用和呈现transient关键字用于防止某些字段序列化的场景。


3
投票

当您不想共享序列化的敏感数据时,需要它。


0
投票

简单地说,瞬态java关键字保护来自Serialize的字段作为非瞬态字段计数器部分。

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

Example

0
投票

根据谷歌暂时意义==只持续很短的时间;暂时的。

现在,如果你想在java中做任何瞬态使用transient关键字。

问:在哪里使用瞬态?

答:通常在java中,我们可以通过在变量中获取数据并将这些变量写入文件来将数据保存到文件中,这个过程称为序列化。现在,如果我们想要避免将可变数据写入文件,我们会将该变量设置为瞬态。

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-keyword的简化示例代码。

transient int result=10;

408
投票

在理解transient关键字之前,必须先了解序列化的概念。如果读者知道序列化,请跳过第一点。

What is serialization?

序列化是使对象的状态持久化的过程。这意味着对象的状态被转换成字节流,用于持久化(例如,在文件中存储字节)或传输(例如,通过网络发送字节)。以同样的方式,我们可以使用反序列化从字节中恢复对象的状态。这是Java编程中的重要概念之一,因为序列化主要用于网络编程。需要通过网络传输的对象必须转换为字节。为此,每个类或接口都必须实现Serializable接口。它是没有任何方法的标记界面。

Now what is the transient keyword and its purpose?

默认情况下,所有对象的变量都转换为持久状态。在某些情况下,您可能希望避免持久化某些变量,因为您不需要持久保存这些变量。所以你可以将这些变量声明为transient。如果变量声明为transient,那么它将不会被持久化。这是transient关键字的主要目的。

我想通过以下示例解释上述两点:

package javabeat.samples;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class NameStore implements Serializable{
    private String firstName;
    private transient String middleName;
    private String lastName;

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

    public String toString(){
        StringBuffer sb = new StringBuffer(40);
        sb.append("First Name : ");
        sb.append(this.firstName);
        sb.append("Middle Name : ");
        sb.append(this.middleName);
        sb.append("Last Name : ");
        sb.append(this.lastName);
        return sb.toString();
    }
}

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

        // reading from object
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
        NameStore nameStore1 = (NameStore)in.readObject();
        System.out.println(nameStore1);
    }
}

输出将如下:

First Name : Steve
Middle Name : null
Last Name : Jobs

中间名声明为transient,因此它不会存储在持久存储中。

Source


82
投票

允许您定义不想序列化的变量。

在对象中,您可能拥有不希望序列化/持久化的信息(可能是对父工厂对象的引用),或者序列化可能没有意义。将这些标记为“瞬态”意味着序列化机制将忽略这些字段。


34
投票

我的小贡献:

什么是瞬态场? 基本上,使用transient关键字修改的任何字段都是瞬态字段。 为什么Java中需要瞬态字段? transient关键字使您可以控制序列化过程,并允许您从此过程中排除某些对象属性。序列化过程用于持久化Java对象,主要是为了在传输或非活动状态时保留它们的状态。有时,不序列化对象的某些属性是有意义的。 您应该在哪些字段标记瞬态? 现在我们知道transient关键字和瞬态字段的目的,了解哪些字段标记瞬态非常重要。静态字段也没有序列化,因此相应的关键字也可以实现。但这可能会破坏你的课堂设计;这是transient关键字拯救的地方。我尽量不允许其值可以从其他字段派生的字段被序列化,所以我将它们标记为瞬态。如果你有一个名为interest的字段,其值可以从其他字段(principalratetime)计算,则无需序列化它。 另一个很好的例子是文章字数。如果要保存整篇文章,则实际上不需要保存单词计数,因为可以在文章被“反序列化”时计算。或者想想伐木工; Logger实例几乎从不需要序列化,因此它们可以是瞬态的。


23
投票

transient变量是可能未序列化的变量。

想到这可能有用的一个例子是,变量只在特定对象实例的上下文中有意义,并且在序列化和反序列化对象后变为无效。在这种情况下,将这些变量变为null非常有用,这样您就可以在需要时使用有用的数据重新初始化它们。


14
投票

transient用于表示类字段不需要序列化。可能最好的例子是Thread场。通常没有理由将Thread序列化,因为它的状态非常“流量特定”。


13
投票

除本机java之外的序列化系统也可以使用此修饰符。例如,Hibernate不会持久标记用@Transient或transient修饰符标记的字段。兵马俑也尊重这个修饰符。

我相信修饰符的比喻意思是“此字段仅供内存使用。不要以任何方式持久存在或将其移出此特定VM。它不可移植”。即你不能在另一个VM内存空间中依赖它的值。很像volatile,意味着你不能依赖某些内存和线程语义。


8
投票

因为并非所有变量都具有可序列化的性质


6
投票

在回答这个问题之前,我必须向您解释SERIALIZATION,因为如果您了解科学计算机中序列化的含义,您就可以轻松理解这个关键字。

序列化当对象通过网络传输/保存在物理介质(文件,...)上时,对象必须“序列化”。序列化转换字节状态对象系列。这些字节在网络上发送/保存,并从这些字节重新创建对象。 例

public class Foo implements Serializable 
{
 private String attr1;
 private String attr2;
 ...
}

现在如果你想要转移/保存这个对象的字段SO,你可以使用关键字qazxsw poi

transient

private transient attr2;

© www.soinside.com 2019 - 2024. All rights reserved.