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 Developer Network 上提供),其中有一节讨论了如何使用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
,因此不会存储在持久存储中。
允许您定义不想序列化的变量。
在对象中,您可能拥有不希望序列化 / 持久化的信息(可能是对父工厂对象的引用),或者序列化可能没有意义。将这些标记为 “瞬态” 意味着序列化机制将忽略这些字段。