为什么 Java 有瞬态字段?

2022-08-31 03:54:49

为什么 Java 有瞬态字段?


答案 1

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

摘自 Java 语言规范,Java SE 7 版第 8.3.1.3 节。短暂的领域

可以标记变量以指示它们不是对象的持久状态的一部分。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();
    }    
}

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

该字段被标记为 ,因此只序列化原始图像,而不是同时保留原始图像和缩略图图像。这意味着保存序列化对象所需的存储更少。(当然,根据系统的要求,这可能是也可能不可取的 - 这只是一个例子。thumbnailImagetransientimage

在反序列化时,将调用 readObject 方法来执行将对象的状态还原回序列化发生的状态所需的任何操作。这里,需要生成缩略图,因此重写该方法,以便通过调用该方法生成缩略图。readObjectgenerateThumbnail

有关其他信息,文章发现 Java 序列化 API(最初在 Sun 开发人员网络上提供)的秘密有一节讨论关键字的使用,并介绍了使用关键字来防止某些字段序列化的方案。transient


答案 2

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

什么是序列化?

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

现在关键字及其目的是什么?transient

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

我想用下面的例子来解释上面的两点(借用本文):

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


推荐