栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Serializable官方实例解析02-将序列化与自定义数据格式结合使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Serializable官方实例解析02-将序列化与自定义数据格式结合使用

官方地址:Using Serialization with a Custom Data Format

将序列化与自定义数据格式结合使用 1. 介绍

演示如何使用 writeObject  和  readObject 方法对自定义数据格式进行编码。当存在大量持久性数据时,该数据应以方便的精简格式存储,如本示例中使用的格式。

此示例使用一个三角形数组,一个对称的二维数组。在序列化期间,仅保存数组的一半。此示例以 writeObject 序列化数组的一半,然后通过反序列化数组的一半并复制以还原数组的另一半来还原readObject中的整个数组。

此示例与使用序列化和可序列化字段 API 示例的不同之处在于,此示例不支持版本控制。此外,由于此示例不使用可外部化接口,因此超类不是考虑因素。

2. 源代码

码云地址:src/test/jack/io/demo/ser/case2 · Jack魏/JDK1.1源码阅读学习 - 码云 - 开源中国 (gitee.com)

import java.io.*;


public class CustomDataExample implements Serializable {

    transient int dimension;
    transient int thearray[][];

    
    CustomDataExample (int dim) {
        dimension = dim;
        thearray = new int[dim][dim];
        arrayInit();
    }

    
    public static void main(String args[]) {
        CustomDataExample corg = new CustomDataExample(4);
        CustomDataExample cnew = null;

        // 序列化原始类对象
        try {
            FileOutputStream fo = new FileOutputStream("cde.tmp");
            ObjectOutputStream so = new ObjectOutputStream(fo);
            so.writeObject(corg);
            so.flush();
            so.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        // 反序列化为新的类对象
        try {
            FileInputStream fi = new FileInputStream("cde.tmp");
            ObjectInputStream si = new ObjectInputStream(fi);
            cnew = (CustomDataExample) si.readObject();
            si.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        // 打印出来检查正确性
        System.out.println();
        System.out.println("Printing the original array...");
        System.out.println(corg);
        System.out.println();
        System.out.println("Printing the new array...");
        System.out.println(cnew);
        System.out.println();
        System.out.println("The original and new arrays should be the same!");
        System.out.println();
    }

    
    private void writeObject(ObjectOutputStream s)
            throws IOException {
        // 即使没有默认的可序列化字段也调用。
        s.defaultWriteObject();

        // 保存维度
        s.writeInt(dimension);

        // 只写入二维数组的1/2
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j <= i; j++) {
                s.writeInt(thearray[i][j]);
            }
        }
    }

    
    private void readObject(ObjectInputStream s)
            throws IOException, ClassNotFoundException  {
        
        s.defaultReadObject();

        // 恢复维度
        dimension = s.readInt();

        // 为数组分配空间
        thearray = new int[dimension][dimension];

        // 先恢复二维数组的1/2
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j <= i; j++) {
                thearray[i][j] = s.readInt();
            }
        }

        // 复制到另一边
        for (int i = 0; i < dimension; i++) {
            for (int j = dimension - 1; j > i; j--) {
                thearray[i][j] = thearray[j][i];
            }
        }
    }

    
    void arrayInit() {
        int x = 0;
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j <= i; j++) {
                thearray[i][j] = x;
                thearray[j][i] = x;
                x++;
            }
        }
    }

    
    public String toString() {

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                sb.append(Integer.toString(thearray[i][j])+ " ");
            }
            sb.append("n");
        }
        return(sb.toString());
    }
}

3. 运行

指令运行:

javac CustomDataExample.java
java CustomDataExample

打印两个数组:

第一个数组显示序列化之前的数组。
第二个数组显示反序列化后的数组。

4. 总结

有个奇怪的地方有没有发现,我们在这个类里面写了writeObject和readObject方法,但是没有调用的地方,那为什么会自己调用呢?
于是我一步一步的调试,终于看到了。
如下图,在ObjectOutputStream类里面有反射调用的(注意这里是JDK1.8版本源码)。
也可以看到调用栈,就很清楚了。

方法名必须和那个名字一样,不然都会序列化失败的,有兴趣的同学可以自己试一下哟~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/868387.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号