# 对象流
就像数据流支持原始数据类型的 I / O,对象流支持 I / O 的对象。大部分,但不是全部,标准类支持对象的序列化。
都实现了标记接口 Serializable
对象流类是
- ObjectInputStream
- ObjectOutputStream
这些类实现 ObjectInput 和 ObjectOutput,它们是 DataInput 和 DataOutput 的子类。 这意味着 数据流 中涵盖的所有原始数据 I/O 方法也在对象流中实现。因此,对象流可以包含原始值和对象值的混合。
public class ObjectStreams {
static final String dataFile = "invoicedata";
static final BigDecimal[] prices = {
// 使用对象类型来表示价格
new BigDecimal("19.99"),
new BigDecimal("9.99"),
new BigDecimal("15.99"),
new BigDecimal("3.99"),
new BigDecimal("4.99") };
static final int[] units = { 12, 8, 13, 29, 50 };
static final String[] descs = { "Java T-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain" };
public static void main(String[] args)
throws IOException, ClassNotFoundException {
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new
BufferedOutputStream(new FileOutputStream(dataFile)));
// 并写一个 日历类型
out.writeObject(Calendar.getInstance());
for (int i = 0; i < prices.length; i ++) {
out.writeObject(prices[i]);
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}
} finally {
out.close();
}
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new
BufferedInputStream(new FileInputStream(dataFile)));
Calendar date = null;
BigDecimal price;
int unit;
String desc;
BigDecimal total = new BigDecimal(0);
date = (Calendar) in.readObject();
System.out.format ("On %tA, %<tB %<te, %<tY:%n", date);
try {
while (true) {
price = (BigDecimal) in.readObject();
unit = in.readInt();
desc = in.readUTF();
System.out.format("You ordered %d units of %s at $%.2f%n",
unit, desc, price);
total = total.add(price.multiply(new BigDecimal(unit)));
}
} catch (EOFException e) {}
System.out.format("For a TOTAL of: $%.2f%n", total);
} finally {
in.close();
}
}
}
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
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
# 复杂对象的输出和输入
writeObject 与 readObject 方法使用简单,但它们包含一些非常复杂的对象管理逻辑。 对于像日历这样的封装原始值的类来说,这并不重要。但是许多对象包含对其他对象的引用。如果 readObject 要从流中重构对象, 则必须能够重构所引用的原始对象的所有对象。这些附加对象可能有自己的引用,依此类推。 在这种情况下,writeObject 遍历对象中所有的引用,并将这些引用写入流。因此,单个调用 writeObject 可能导致大量对象被写入流。
如下图所示:
您可能会想,如果同一流中的两个对象都包含对单个对象的引用,会发生什么。他们回读时是否会指向单个对象?答案:“是”。
因此,如果您将一个对象显式写入一个流两次,那么您真的只写两次引用。例如,如果以下代码将一个对象 ob 两次写入流中:
Object ob = new Object();
out.writeObject(ob);
out.writeObject(ob);
Object ob1 = in.readObject();
Object ob2 = in.readObject();
1
2
3
4
5
6
2
3
4
5
6
那么读取出来的引用地址是一样的。
然而,如果单个对象被写入两个不同的流,则它被有效地重复 - 读取两个流的单个程序将看到两个不同的对象。
← 数据流 文件 I/O(nio.2) →