Java|Java transient 关键字
问:transient 关键字能实现什么?
答:当对象被序列化时(写入字节序列到目标文件)时,transient 阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象 —— 数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为 java.io.InputStream
的变量,序列化时这些变量引用的输入流无法被打开。
问:如何使用 transient?
答:包含实例变量声明中的 transient 修饰符。下面代码提供了小的演示。
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class ClassLib implements Serializable {
private transient InputStream is;
private int majorVer;
private int minorVer;
ClassLib(InputStream is) throws IOException {
System.out.println("ClassLib(InputStream) called");
this.is = is;
DataInputStream dis;
if (is instanceof DataInputStream)
dis = (DataInputStream) is;
else
dis = new DataInputStream(is);
if (dis.readInt() != 0xcafebabe)
throw new IOException("not a .class file");
minorVer = dis.readShort();
majorVer = dis.readShort();
}int getMajorVer() {
return majorVer;
}int getMinorVer() {
return minorVer;
}void showIS() {
System.out.println(is);
}
}public class TransDemo {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("usage: java TransDemo classfile");
return;
}
ClassLib cl = new ClassLib(new FileInputStream(args[0]));
System.out.printf("Minor version number: %d%n", cl.getMinorVer());
System.out.printf("Major version number: %d%n", cl.getMajorVer());
cl.showIS();
try (FileOutputStream fos = new FileOutputStream("x.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(cl);
}cl = null;
try (FileInputStream fis = new FileInputStream("x.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
System.out.println();
cl = (ClassLib) ois.readObject();
System.out.printf("Minor version number: %d%n", cl.getMinorVer());
System.out.printf("Major version number: %d%n", cl.getMajorVer());
cl.showIS();
} catch (ClassNotFoundException cnfe) {
System.err.println(cnfe.getMessage());
}
}
}
上面代码中声明 ClassLib 和 TransDemo 类。ClassLib 是一个读取 Java 类文件的库,并且实现了
java.io.Serializable
接口,从而这些实例能被序列化和反序列化。TransDemo 是一个用来序列化和反序列化 ClassLib 实例的应用类。ClassLib 声明它的实例变量为 transient,原因是它可以毫无意义的序列化一个输入流(像上面讲述的那样)。事实上,如果此变量不是 transient 的话,当反序列化 x.ser 的内容时,则会抛出
java.io.NotSerializableException
,原因是 InputStream 没有实现 Serializable 接口。编译运行上面代码你或许会看到类似下面的输出:
ClassLib(InputStream) called
Minor version number: 0
Major version number: 51
java.io.FileInputStream@79f1e0e0Minor version number: 0
Major version number: 51
null
以上输出表明:当对象被重构时,没有构造方法调用。此外,is 假定默认为 null,相比较,当 ClassLib 对象序列化时,majorVer 和 minorVer 是有值的。
问:类中的成员变量中可以使用 transient 吗? 答:问题答案请看如下代码段。
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Foo implements Serializable
{
public static int w = 1;
public static transient int x = 2;
public int y = 3;
public transient int z = 4;
}public class TransDemo
{
public static void main(String[] args) throws IOException
{
Foo foo = new Foo();
System.out.printf("w: %d%n", Foo.w);
System.out.printf("x: %d%n", Foo.x);
System.out.printf("y: %d%n", foo.y);
System.out.printf("z: %d%n", foo.z);
try (FileOutputStream fos = new FileOutputStream("x.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos))
{
oos.writeObject(foo);
}foo = null;
try (FileInputStream fis = new FileInputStream("x.ser");
ObjectInputStream ois = new ObjectInputStream(fis))
{
System.out.println();
foo = (Foo) ois.readObject();
System.out.printf("w: %d%n", Foo.w);
System.out.printf("x: %d%n", Foo.x);
System.out.printf("y: %d%n", foo.y);
System.out.printf("z: %d%n", foo.z);
}
catch (ClassNotFoundException cnfe)
{
System.err.println(cnfe.getMessage());
}
}
}
编译运行上面代码可以看到如下输出:
w: 1
x: 2
y: 3
z: 4w: 1
x: 2
y: 3
z: 0
这个输出告诉我们,实例变量 y 是被序列化的,z 却没有,它被标记 transient。但是,当 Foo 被序列化时,它并没有告诉我们,是否变量 w 和 x 被序列化和反序列化,是否只是以普通类初始化方式初始。因为 z 是 transient,所以不能序列化。此外,即使它们标记 transien,w 和 x 不能被序列化,原因是它们类变量不能序列化。
【Java|Java transient 关键字】翻译: ImportNew.com - xbing
原文链接: http://www.javaworld.com/article/2074911/java-se/transience.html
译文链接: http://www.importnew.com/12611.html
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)
- java之static、static|java之static、static final、final的区别与应用
- 越努力越幸福