当对象中包含静态字段时,该如何进行序列化呢?
我们先来看一个模拟 CAD 系统的例子。
Shape 为一个抽象基类,定义了基本的构造方法、color 的 get/set 抽象方法、生成三个导出类的工厂方法,以及改写了 toString() 方法。
abstract class Shape implements Serializable {
public static final int RED = 1, BLUE = 2, GREEN = 3;
private int xPos, yPos, dimension;
private static Random rand = new Random(47);
private static int counter = 0;
public abstract void setColor(int newColor);
public abstract int getColor();
public Shape(int xPos, int yPos, int dimension) {
this.xPos = xPos;
this.yPos = yPos;
this.dimension = dimension;
}
@Override
public String toString() {
return getClass() + "{" +
"color=" + getColor() +
",xPos=" + xPos +
", yPos=" + yPos +
", dimension=" + dimension +
"}\n";
}
public static Shape randomFactory() {
int xVal = rand.nextInt(100);
int yVal = rand.nextInt(100);
int dim = rand.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);
}
}
}
然后,展示 Shape 的三个导出类 Circle 、Square 、Line 。
public class Circle extends Shape {
private static int color = RED;
public Circle(int xPos, int yPos, int dimension) {
super(xPos, yPos, dimension);
}
@Override
public void setColor(int newColor) {
color=newColor;
}
@Override
public int getColor() {
return color;
}
}
public class Square extends Shape {
private static int color;
public Square(int xPos, int yPos, int dimension) {
super(xPos, yPos, dimension);
color = RED;
}
@Override
public void setColor(int newColor) {
color = newColor;
}
@Override
public int getColor() {
return color;
}
}
public class Line extends Shape {
private static int color = RED;
public Line(int xPos, int yPos, int dimension) {
super(xPos, yPos, dimension);
}
@Override
public void setColor(int newColor) {
color = newColor;
}
@Override
public int getColor() {
return color;
}
public static void serializeStaticState(ObjectOutputStream os) throws IOException {
os.writeInt(color);
}
public static void deserializeStaticState(ObjectInputStream in) throws IOException {
color = in.readInt();
}
}
接下来,来看 Shape 集合的序列化过程。
public class StoreCADState {
public static void main(String[] args) throws IOException {
List<Shape> shapes = new ArrayList<>();
for (int i = 0; i < 10; i++) {
shapes.add(Shape.randomFactory());
}
for (int i = 0; i < 10; i++) {
shapes.get(i).setColor(Shape.GREEN);
}
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("CADState.out"));
Line.serializeStaticState(out);
out.writeObject(shapes);
System.out.println(shapes);
}
}
生成 Shape 集合后,将集合中的 Shape 导出类的 color 都设置为 Shape.GREEN
。
Line.serializeStaticState(ObjectOutputStream os)
将Line 中的 color 变量写入序列化文件中,随后将整个 Shape 集合进行序列化。
[class mtn.baymax.charpter18.Circle{color=3,xPos=58, yPos=55, dimension=93}
, class mtn.baymax.charpter18.Square{color=3,xPos=61, yPos=61, dimension=29}
, class mtn.baymax.charpter18.Line{color=3,xPos=68, yPos=0, dimension=22}
, class mtn.baymax.charpter18.Circle{color=3,xPos=7, yPos=88, dimension=28}
, class mtn.baymax.charpter18.Square{color=3,xPos=51, yPos=89, dimension=9}
, class mtn.baymax.charpter18.Line{color=3,xPos=78, yPos=98, dimension=61}
, class mtn.baymax.charpter18.Circle{color=3,xPos=20, yPos=58, dimension=16}
, class mtn.baymax.charpter18.Square{color=3,xPos=40, yPos=11, dimension=22}
, class mtn.baymax.charpter18.Line{color=3,xPos=4, yPos=83, dimension=6}
, class mtn.baymax.charpter18.Circle{color=3,xPos=75, yPos=10, dimension=42}
]
从打印结果可以看出所有的 Shape 导出类的 color 都被更改为 3 。
那么,再来看看反序列化的过程。
public class RecoverCADState {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("CADState.out"));
Line.deserializeStaticState(in);
List<Shape> shapes = (List<Shape>) in.readObject();
System.out.println(shapes);
}
}
[class mtn.baymax.charpter18.Circle{color=1,xPos=58, yPos=55, dimension=93}
, class mtn.baymax.charpter18.Square{color=0,xPos=61, yPos=61, dimension=29}
, class mtn.baymax.charpter18.Line{color=3,xPos=68, yPos=0, dimension=22}
, class mtn.baymax.charpter18.Circle{color=1,xPos=7, yPos=88, dimension=28}
, class mtn.baymax.charpter18.Square{color=0,xPos=51, yPos=89, dimension=9}
, class mtn.baymax.charpter18.Line{color=3,xPos=78, yPos=98, dimension=61}
, class mtn.baymax.charpter18.Circle{color=1,xPos=20, yPos=58, dimension=16}
, class mtn.baymax.charpter18.Square{color=0,xPos=40, yPos=11, dimension=22}
, class mtn.baymax.charpter18.Line{color=3,xPos=4, yPos=83, dimension=6}
, class mtn.baymax.charpter18.Circle{color=1,xPos=75, yPos=10, dimension=42}
]
我们发现 Circle 和 Square 原本存储的 color 值丢失了,变为了该字段的默认值(Circle 的 color 默认为 RED = 1 和 Square 的 color 默认没有初始化,故为 0 )。
而 Line 中的 color 则被顺利还原了,这是因为之前我们在序列化时,通过Line.serializeStaticState(ObjectOutputStream os)
手动将 color 写入了序列化文件中;在反序列化时,再通过 Line.deserializeStaticState(ObjectOutputStream os)
重设 Line 中静态变量 color 的值。
综上所述可以得出,Class 类在序列化时,并不会保存当前对象的 static 值,如果我们需要保存 static 值的实时状态,则需要在序列化时手动写入,反序列化时手动读取进行恢复。
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!