为什么Java有瞬态字段?

为什么Java有瞬态字段?


Java中的transient关键字用于指示不应序列化字段。

从Java语言规范,Java SE 7 Edition,第8.3.1.3节。 transient领域:

变量可能被标记为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方法来生成缩略图。

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


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

什么是序列化?

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

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

默认情况下,所有对象的变量都转换为持久状态。 在某些情况下,您可能想要避免保留一些变量,因为您不需要保存这些变量。 所以你可以声明这些变量是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 ,所以它不会被存储在永久存储器中。

资源


允许你定义你不想串行化的变量。

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

链接地址: http://www.djcxy.com/p/3475.html

上一篇: Why does Java have transient fields?

下一篇: What is the best comment in source code you have ever encountered?