当对象中包含静态字段时,该如何进行序列化呢?
我们先来看一个模拟 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 { Listshapes = 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); Listshapes = (List ) 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 值的实时状态,则需要在序列化时手动写入,反序列化时手动读取进行恢复。
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)