美文网首页
java对象的序列化与反序列化(Serializable)

java对象的序列化与反序列化(Serializable)

作者: 漫不经心v | 来源:发表于2018-12-26 11:17 被阅读0次
    先看看概念介绍:
    • 序列化:把对象转换为字节序列的过程称为对象的序列化。
    • 反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
    应用场景
    • 数据的持久化。简单的说,就是把jvm中的对象的状态写入到硬盘里
    • 网络之间的通信。把网络这端的对象此刻的属性状态通过序列化成字节,网络另一端接收到字节转换成对象。
    让我们用代码加深理解吧

    一、这是一个要被序列化和反序列化的类:

    /**
     *需要传输或持久化的java对象,实现Serializable接口
     *
     */
    import java.io.Serializable;
    
    public class SerializableBean implements Serializable {
        
        private static final long serialVersionUID = 1L;
    
        private String name;
        private String param;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getParam() {
            return param;
        }
        public void setParam(String param) {
            this.param = param;
        }
    }
    
    

    二、这是一个把SerializableBean序列化和反序列化的类:

    /**
     *
     *把SerializableBean序列化和反序列化的类
     */
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    public class SerializableTest {
    
        public static void main(String[] args) {
            
            String path = "D://SAFile";
            // 实例化SerializableBean,设置值
            SerializableBean sa = new SerializableBean();
            sa.setName("Cyf");
            sa.setParam("test");
    
            // 写入文件
            try {
                ObjectOutputStream oos = new ObjectOutputStream(
                        new FileOutputStream(path));
                oos.writeObject(sa);
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            //读取文件输出
            File file = new File(path);
            FileInputStream fis;
            try {
                fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                SerializableBean invsa = (SerializableBean) ois.readObject();
                System.out.print(invsa.getClass() + " " 
                        + invsa.getName() + " " 
                        + invsa.getParam());
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    1.第一段代码中,首先我们定义了一个实现Serializable接口的SerializableBean类,这个类中有name和param属性。
    2.第二段代码中,分为两部分:一部分是实例化SerializableBean类,并设置属性值,然后把这个类序列化持久化到D盘中;另一部分是反序列化并输出这个对象的属性值。

    序列化和反序列化的扩展点
    1.serialVersionUID的值

    需要被序列化和反序列化的对象设置一个serialVersionUID值:

    private static final long serialVersionUID = 1L;
    

    这个值就如同序列化和反序列化之间的版本约定。举个例子:如果我先把反序列化部分代码屏蔽,在序列化的时候设置SerializableBean类的serialVersionUID值为1L,然后屏蔽序列化部分代码,在反序列化的时候设置SerializableBean类的serialVersionUID值为2L,就会报错:

    java.io.InvalidClassException: 
    local class incompatible: stream classdesc serialVersionUID = 1,
    local class serialVersionUID = 2
    
    2.transient

    若我们在SerializableBean类中增加一个用transient修饰的属性:

        private transient String constant;
        public String getConstant() {
            return constant;
        }
        public void setConstant(String constant) {
            this.constant = constant;
        }
    

    在序列化之前设置constant值

        sa.setConstant("CONSTANT");
    

    在反序列化部分代码中修改输出:

         System.out.print(invsa.getClass() + " " 
                        + invsa.getName() + " " 
                        + invsa.getParam() + " "
                        + invsa.getConstant());
    

    输出结果:

    class com.test.SerializableBean Cyf test null
    

    constant的值为null。
    可以得出用transient修饰的属性将不被序列化。

    3.Externalizable

    Externalizable继承Serializable,扩展了writeExternal(),readExternal()这两个方法。
    若我们直接把SerializableBean类实现接口改成Externalizable,序列化和反序列化之后的输出是:

        class com.test.SerializableBean null null null
    

    我们发现,之前的三个属性的值都没被序列化。
    那么如何来设置属性值呢?
    这时候就要用到writeExternal(),readExternal()这两个方法了:

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(name);
            out.writeObject(param);
        }
    
        @Override
        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            name = (String) in.readObject();
            param = (String) in.readObject();
        }
    

    再次输出:

        class com.test.ExternalizableBean Cyf test
    

    序列化和反序列化End。

    相关文章

      网友评论

          本文标题:java对象的序列化与反序列化(Serializable)

          本文链接:https://www.haomeiwen.com/subject/zatxhqtx.html