为什么Java有临时字段?

为什么Java有临时字段?,java,field,transient,Java,Field,Transient,为什么Java有临时字段?允许您定义不想序列化的变量 在对象中,您可能有不希望序列化/持久化的信息(可能是对父工厂对象的引用),或者序列化没有意义。将这些标记为“transient”意味着序列化机制将忽略这些字段。因为并非所有变量都具有可序列化性质transient变量可能是不可序列化的变量 这可能有用的一个例子是,变量仅在特定对象实例的上下文中才有意义,并且一旦序列化和反序列化了对象,这些变量就会变得无效。在这种情况下,将这些变量改为null,以便在需要时使用有用的数据重新初始化它们是很有用的

为什么Java有临时字段?

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


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

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

transient变量可能是不可序列化的变量


这可能有用的一个例子是,变量仅在特定对象实例的上下文中才有意义,并且一旦序列化和反序列化了对象,这些变量就会变得无效。在这种情况下,将这些变量改为
null
,以便在需要时使用有用的数据重新初始化它们是很有用的

当您不想共享与序列化相关的一些敏感数据时,需要使用它。

Java中的
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
,因此仅序列化原始
图像,而不是同时保留原始图像和缩略图图像。这意味着保存序列化对象需要更少的存储空间。(当然,这可能是可取的,也可能不是可取的,这取决于系统的需求——这只是一个示例。)

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


有关更多信息,请参阅本文(最初在Sun开发者网络上提供)有一节讨论了transient
关键字用于防止某些字段序列化的用法,并介绍了一个场景。

除本机java之外的序列化系统也可以使用此修饰符。例如,Hibernate不会保留标记有@TransientTransient修饰符的字段。兵马俑也尊重这种修饰物


我相信修饰符的比喻意义是“此字段仅供内存使用。不要以任何方式将其保留或移动到特定VM之外。它不可移植”。i、 e.您不能依赖于它在另一个VM内存空间中的值。与volatile非常相似,volatile意味着不能依赖于特定的内存和线程语义。

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

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

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

现在什么是
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);
    }
}
输出将如下所示:

名字:史蒂夫
中间名:null
姓氏:乔布斯
中间名声明为
瞬态
,因此它不会存储在持久性存储器中


我的小小贡献:

什么是瞬态场?
基本上,任何用
transient
关键字修改的字段都是transient字段。

为什么Java中需要临时字段?
transient
关键字为您提供了对序列化过程的一些控制,并允许您从此过程中排除某些对象属性。序列化过程用于持久化Java对象,主要是为了在传输或不活动Java对象时保留它们的状态。有时,这是有意义的,而不是t
transient int result=10;
public class Foo implements Serializable 
{
 private String attr1;
 private String attr2;
 ...
}
private transient attr2;
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;

   }
}
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);
    }
}