静态字段如何序列化? --《JAVA编程思想》88

博客讨论了在Java中如何处理静态字段的序列化问题。通过一个CAD系统示例,展示了静态字段在默认情况下不被序列化的情况,并提供了手动序列化和反序列化静态变量的方法。在序列化过程中,静态变量不会被保存,除非在代码中特别处理。在反序列化时,静态变量的状态可能丢失,除非在反序列化时手动恢复。文章强调了如果需要保存静态变量的实时状态,必须在序列化和反序列化时分别进行写入和读取操作。

当对象中包含静态字段时,该如何进行序列化呢?

我们先来看一个模拟 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 值的实时状态,则需要在序列化时手动写入,反序列化时手动读取进行恢复。


本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值