在Java中如何使用transient

来源:互联网 发布:淘宝年消费怎么查 编辑:程序博客网 时间:2024/06/04 18:01

Java语言的transient不像class、synchronized和其他熟悉的关键字那样众所周知,因而它会出现在一些面试题中。这篇文章我将为大家讲解transient。

transient的用途

Q:transient关键字能实现什么?

A:当对象被序列化时(写入字节序列到目标文件)时,transient阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为java.io.InputStream的变量,序列化时这些变量引用的输入流无法被打开。

transient使用介绍

Q:如何使用transient?

A:包含实例变量声明中的transient修饰符。片段1提供了小的演示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
importjava.io.DataInputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.InputStream;
importjava.io.IOException;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.io.Serializable;
 
classClassLib implementsSerializable {
    privatetransient InputStream is;
 
    privateint majorVer;
    privateint minorVer;
 
    ClassLib(InputStream is) throwsIOException {
        System.out.println("ClassLib(InputStream) called");
        this.is = is;
        DataInputStream dis;
        if(is instanceofDataInputStream)
            dis = (DataInputStream) is;
        else
            dis = newDataInputStream(is);
        if(dis.readInt() != 0xcafebabe)
            thrownew IOException("not a .class file");
        minorVer = dis.readShort();
        majorVer = dis.readShort();
    }
 
    intgetMajorVer() {
        returnmajorVer;
    }
 
    intgetMinorVer() {
        returnminorVer;
    }
 
    voidshowIS() {
        System.out.println(is);
    }
}
 
publicclass TransDemo {
    publicstatic void main(String[] args) throwsIOException {
        if(args.length != 1) {
            System.err.println("usage: java TransDemo classfile");
            return;
        }
        ClassLib cl = newClassLib(newFileInputStream(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 = newFileOutputStream("x.ser");
                ObjectOutputStream oos = newObjectOutputStream(fos)) {
            oos.writeObject(cl);
        }
 
        cl = null;
 
        try(FileInputStream fis = newFileInputStream("x.ser");
                ObjectInputStream ois = newObjectInputStream(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());
        }
    }
}

片段1:序列化和反序列化ClassLib对象

片段1中声明ClassLib和TransDemo类。ClassLib是一个读取Java类文件的库,并且实现了java.io.Serializable接口,从而这些实例能被序列化和反序列化。TransDemo是一个用来序列化和反序列化ClassLib实例的应用类。

ClassLib声明它的实例变量为transient,原因是它可以毫无意义的序列化一个输入流(像上面讲述的那样)。事实上,如果此变量不是transient的话,当反序列化x.ser的内容时,则会抛出java.io.NotSerializableException,原因是InputStream没有实现Serializable接口。

编译片段1:javac TransDemo.java;带一个参数TransDemo.class运行应用:java TransDemo TransDemo.class。你或许会看到类似下面的输出:

1
2
3
4
5
6
7
8
ClassLib(InputStream) called
Minor version number: 0
Major version number: 51
java.io.FileInputStream@79f1e0e0
 
Minor version number: 0
Major version number: 51
null

以上输出表明:当对象被重构时,没有构造方法调用。此外,is假定默认为null,相比较,当ClassLib对象序列化时,majorVer和minorVer是有值的。

类中的成员变量和transient

Q:类中的成员变量中可以使用transient吗?

A:问题答案请看片段2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
publicclass TransDemo {
    publicstatic void main(String[] args) throwsIOException {
        Foo foo = newFoo();
        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 = newFileOutputStream("x.ser");
                ObjectOutputStream oos = newObjectOutputStream(fos)) {
            oos.writeObject(foo);
        }
 
        foo = null;
 
        try(FileInputStream fis = newFileInputStream("x.ser");
                ObjectInputStream ois = newObjectInputStream(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());
        }
    }
}

片段2:序列化和反序列化Foo对象

片段2有点类似片段1。但不同的是,序列化和反序列化的是Foo对象,而不是ClassLib。此外,Foo包含一对变量,w和x,以及实例变量y和z。

编译片段2(javac TransDemo.java)并运行应用(java TransDemo)。你可以看到如下输出:

1
2
3
4
5
6
7
8
9
w: 1
x: 2
y: 3
z: 4
 
w: 1
x: 2
y: 3
z: 0

这个输出告诉我们,实例变量y是被序列化的,z却没有,它被标记transient。但是,当Foo被序列化时,它并没有告诉我们,是否变量w和x被序列化和反序列化,是否只是以普通类初始化方式初始。对于答案,我们需要查看x.ser的内容。

下面显示x.ser十六进制:

1
2
00000000AC ED 0005 73 72 00 03 46 6F 6F FC 7A 5D 821D ....sr..Foo.z]..
00000010D2 9D 3F 0200 01 49 00 01 79 78 70 00 00 00 03 ..?...I..yxp....

由于JavaWorld中的“The Java serialization algorithm revealed”这篇文章,我们发现输出的含义:

  • AC ED 序列化协议标识
  • 00 05 流版本号
  • 73 表示这是一个新对象
  • 72 表示这是一个新的类
  • 00 03 表示类名长度(3)
  • 46 6F 6F 表示类名(Foo)
  • FC 7A 5D 82 1D D2 9D 3F 表示类的串行版本标识符
  • 02 表示该对象支持序列化
  • 00 01 表示这个类的变量数量(1)
  • 49 变量类型代码 (0×49, 或I, 表示int)
  • 00 01 表示变量名长度(1)
  • 79 变量名称(y)
  • 78 表示该对象可选的数据块末端
  • 70 表示我们已经到达类层次结构的顶部
  • 00 00 00 03 表示y的值(3)

显而易见,只有实例变量y被序列化。因为z是transient,所以不能序列化。此外,即使它们标记transien,w和x不能被序列化,原因是它们类变量不能序列化。

原文链接: javaworld 翻译: ImportNew.com xbing

译文链接: http://www.importnew.com/12611.html

本文由 ImportNew - xbing 翻译自 javaworld

from: http://www.importnew.com/12611.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 绿植施肥施多了怎么办 盆栽肥料放多了怎么办 三环复合肥怎么办啊 母猪下崽后不吃食怎么办 猪自配料料槽不下怎么办 美甲边缘起翘怎么办 猪粪流到鱼塘里鱼死了怎么办啊 在基本农田建有机肥厂怎么办 有机肥厂的环评怎么办 织玻璃纤维网布环评怎么办 吃了受潮的奶粉怎么办 喝了受潮的奶粉怎么办 刚买的奶粉受潮怎么办 羊不小心吃了化肥怎么办 阿胶粉结成块了怎么办 半桶奶粉受潮了怎么办 眉粉受潮了结块怎么办 刚买的奶粉结块怎么办 袋装白糖成坨了怎么办 一袋子白糖硬了怎么办 粉饼上有一层油怎么办 葡萄后期氮肥施用过多怎么办 没洗的菜吃了怎么办 闻了汽油味头晕怎么办 碰到绿萝的汁液怎么办 吃了带农药水果怎么办 开槽模切一体机模切时开槽怎么办 柔版印刷走纸歪斜怎么办 美团外卖一天8单怎么办 单位显示器丢了怎么办员工赔 纸板板门起泡了怎么办 卖家要我开出质量问题证明怎么办 闲鱼买到的商品不符合描述怎么办 寄出去的东西碎了怎么办 闲鱼快递损坏了怎么办 寄快递东西坏了怎么办 快递邮寄东西坏了怎么办 快递被别人拆了怎么办 淘宝买的东西包装破损怎么办 寄血液被退回来怎么办 快递被安检扣了怎么办