按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
abstract public int getColor();
public Shape(int xVal; int yVal; int dim) {
xPos = xVal;
yPos = yVal;
dimension = dim;
}
public String toString() {
return getClass()。toString() +
〃 color'〃 + getColor() +
〃' xPos'〃 + xPos +
〃' yPos'〃 + yPos +
〃' dim'〃 + dimension + 〃'n〃;
}
public static Shape randomFactory() {
int xVal = r。nextInt() % 100;
328
…………………………………………………………Page 330……………………………………………………………
int yVal = r。nextInt() % 100;
int dim = r。nextInt() % 100;
switch(counter++ % 3) {
default:
case 0: return new Circle(xVal; yVal; dim);
case 1: return new Square(xVal; yVal; dim);
case 2: return new Line(xVal; yVal; dim);
}
}
}
class Circle extends Shape {
private static int color = RED;
public Circle(int xVal; int yVal; int dim) {
super(xVal; yVal; dim);
}
public void setColor(int newColor) {
color = newColor;
}
public int getColor() {
return color;
}
}
class Square extends Shape {
private static int color;
public Square(int xVal; int yVal; int dim) {
super(xVal; yVal; dim);
color = RED;
}
public void setColor(int newColor) {
color = newColor;
}
public int getColor() {
return color;
}
}
class Line extends Shape {
private static int color = RED;
public static void
serializeStaticState(ObjectOutputStream os)
throws IOException {
os。writeInt(color);
}
public static void
deserializeStaticState(ObjectInputStream os)
throws IOException {
color = os。readInt();
}
public Line (int xVal; int yVal; int dim) {
super(xVal; yVal; dim);
329
…………………………………………………………Page 331……………………………………………………………
}
public void setColor(int newColor) {
color = newColor;
}
public int getColor() {
return color;
}
}
public class CADState {
public static void main(String'' args)
throws Exception {
Vector shapeTypes; shapes;
if(args。length == 0) {
shapeTypes = new Vector();
shapes = new Vector();
// Add handles to the class objects:
shapeTypes。addElement(Circle。class);
shapeTypes。addElement(Square。class);
shapeTypes。addElement(Line。class);
// Make some shapes:
for(int i = 0; i 《 10; i++)
shapes。addElement(Shape。randomFactory());
// Set all the static colors to GREEN:
for(int i = 0; i 《 10; i++)
((Shape)shapes。elementAt(i))
。setColor(Shape。GREEN);
// Save the state vector:
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream(〃CADState。out〃));
out。writeObject(shapeTypes);
Line。serializeStaticState(out);
out。writeObject(shapes);
} else { // There's a mand…line argument
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream(args'0'));
// Read in the same order they were written:
shapeTypes = (Vector)in。readObject();
Line。deserializeStaticState(in);
shapes = (Vector)in。readObject();
}
// Display the shapes:
System。out。println(shapes);
}
} ///:~
Shape (几何形状)类“实现了可序列化”(implements Serializable),所以从Shape 继承的任何东西也
都会自动“可序列化”。每个 Shape 都包含了数据,而且每个衍生的Shape 类都包含了一个特殊的 static 字
段,用于决定所有那些类型的 Shape 的颜色(如将一个 static字段置入基础类,结果只会产生一个字段,因
为 static 字段未在衍生类中复制)。可对基础类中的方法进行覆盖处理,以便为不同的类型设置颜色
330
…………………………………………………………Page 332……………………………………………………………
(static 方法不会动态绑定,所以这些都是普通的方法)。每次调用randomFactory()方法时,它都会创建
一个不同的 Shape (Shape 值采用随机值)。
Circle (圆)和Square (矩形)属于对Shape 的直接扩展;唯一的差别是Circle 在定义时会初始化颜色,
而Square 在构建器中初始化。Line (直线)的问题将留到以后讨论。
在main()中,一个Vector 用于容纳Class 对象,而另一个用于容纳形状。若不提供相应的命令行参数,就
会创建 shapeTypes Vector,并添加Class 对象。然后创建 shapes Vector,并添加Shape 对象。接下来,所
有 static color 值都会设成 GREEN,而且所有东西都会序列化到文件 CADState。out。
若提供了一个命令行参数(假设CADState。out),便会打开那个文件,并用它恢复程序的状态。无论在哪种
情况下,结果产生的Shape 的Vector 都会打印出来。下面列出它某一次运行的结果:
》java CADState
'class Circle color'3' xPos'…51' yPos'…99' dim'38'
; class Square color'3' xPos'2' yPos'61' dim'…46'
; class Line color'3' xPos'51' yPos'73' dim'64'
; class Circle color'3' xPos'…70' yPos'1' dim'16'
; class Square color'3' xPos'3' yPos'94' dim'…36'
; class Line color'3' xPos'…84' yPos'…21' dim'…35'
; class Circle color'3' xPos'…75' yPos'…43' dim'22'
; class Square color'3' xPos'81' yPos'30' dim'…45'
; class Line color'3' xPos'…29' yPos'92' dim'17'
; class Circle color'3' xPos'17' yPos'90' dim'…76'
'
》java CADState CADState。out
'class Circle color'1' xPos'…51' yPos'…99' dim'38'
; class Square color'0' xPos'2' yPos'61' dim'…46'
; class Line color'3' xPos'51' yPos'73' dim'64'
; class Circle color'1' xPos'…70' yPos'1' dim'16'
; class Square color'0' xPos'3' yPos'94' dim'…36'
; class Line color'3' xPos'…84' yPos'…21' dim'…35'
; class Circle color'1' xPos'…75' yPos'…43' dim'22'
; class Square color'0' xPos'81' yPos'30' dim'…45'
; class Line color'3' xPos'…29' yPos'92' dim'17'
; class Circle color'1' xPos'17' yPos'90' dim'…76'
'
从中可以看出,xPos,yPos 以及dim 的值都已成功保存和恢复出来。但在获取 static信息时却出现了问
题。所有“3”都已进入,但没有正常地出来。Circle 有一个 1值(定义为 RED),而Square 有一个 0 值
(记住,它们是在构建器里初始化的)。看上去似乎static 根本没有得到初始化!实情正是如此——尽管类
Class 是“可以序列化的”,但却不能按我们希望的工作。所以假如想序列化static值,必须亲自动手。
这正是 Line 中的 serializeStaticState()和 deserializeStaticState()两个 static 方法的用途。可以看
到,这两个方法都是作为存储和恢复进程的一部分明确调用的(注意写入序列化文件和从中读回的顺序不能
改变)。所以为了使CADState。java 正确运行起来,必须采用下述三种方法之一:
(1) 为几何形状添加一个serializeStaticState()和 deserializeStaticState()。
(2) 删除Vector shapeTypes 以及与之有关的所有代码
(3) 在几何形状内添加对新序列化和撤消序列化静态方法的调用
要注意的另一个问题是安全,因为序列化处理也会将private 数据保存下来。若有需要保密的字段,应将其
标记成 transient。但在这之后,必须设计一种安全的信息保存方法。这样一来,一旦需要恢复,就可以重
设那些private 变量。
331
…………………………………………………………Page 333……………………………………………………………
10。10 总结
Java IO 流库能满足我们的许多基本要求:可以通过控制台、文件、内存块甚至因特网(参见第 15章)进行
读写。可以创建新的输入和输出对象类型(通过从 InputStream和 OutputStream 继承)。向一个本来预期为
收到字串的方法传递一个对象时,由于Java 已限制了“自动类型转换”,所以会自动调用toString()方
法。而我们可以重新定义这个 toString(),扩展一个数据流能接纳的对象种类。
在 IO 数据流库的联机文档和设计过程中,仍有些问题没有解决。比如当我们打开一个文件以便输出时,完全
可以指定一旦有人试图覆盖该文件就“掷”出一个违例——有的编程系统允许我们自行指定想打开一个输出
文件,但唯一的�