java序列化(一)

今天我们来探讨一下java的序列化与反序列化。之前对此一直有概念,但是并没有真正的去测试。大家都知道,所谓的序列化就是把java代码读取到一个文件中,反序列化就是从文件中读取出对象。在网络传输过程中,我们也需要对对象进行序列化,因为一个对象是不能进行传输的。下面先上代码

package serializable;

import java.io.*;

public class SerializableTest implements Serializable {
    private static final Long serialVersionUID = 1L;

    private String name;

    public String sex;

    protected int age;

    private static int id;

    transient private float height;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static int getId() {
        return id;
    }

    public static void setId(int id) {
        SerializableTest.id = id;
    }

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }

    public static void main(String[] args) throws Exception {
        serializable();
        deSerializable();
    }

    /**
     * 序列化
     * @throws IOException
     */
    private static void serializable() throws IOException {
        SerializableTest serializableTest = new SerializableTest();
        serializableTest.setAge(25);
        serializableTest.setId(122528);
        serializableTest.setName("张三");
        serializableTest.setSex("男");
        serializableTest.setHeight(175);

        FileOutputStream fos = new FileOutputStream("serializableTest.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(serializableTest);
        oos.flush();
        oos.close();
    }

    /**
     * 反序列化
     * @throws Exception
     */
    public static void deSerializable() throws Exception{
        FileInputStream fis = new FileInputStream("serializableTest.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        SerializableTest serializableTest = (SerializableTest) ois.readObject();
        System.out.println("serializableTest.getAge() = " + serializableTest.getAge());
        System.out.println("serializableTest.getName() = " + serializableTest.getName());
        System.out.println("serializableTest.getSex() = " + serializableTest.getSex());
        System.out.println("serializableTest.getHeight() = " + serializableTest.getHeight());
        System.out.println("serializableTest.getId() = " + serializableTest.getId());
    }
}

此类中,包括了private、public、protected、static和transient修饰的属性,我们先看下运行结果

serializableTest.getAge() = 25
serializableTest.getName() = 张三
serializableTest.getSex() = 男
serializableTest.getHeight() = 0.0
serializableTest.getId() = 122528

可以发现transient修饰的属性并没有被序列化,这也是我们所认知的。但是static修饰的属性也不应该被序列化才对,现在对象已经被我们读到文件中了,在单独执行一次反序列化方法。

    public static void main(String[] args) throws Exception {
        //serializable();
        deSerializable();
    }

执行结果如下:

serializableTest.getAge() = 25
serializableTest.getName() = 张三
serializableTest.getSex() = 男
serializableTest.getHeight() = 0.0
serializableTest.getId() = 0

现在得到的Id的值是0,也就是这个值并没有被序列化存储到文件中。

最后再说一下序列化版本号的意义。在我的理解看来,次版本号就是为了保证程序的稳定性,如果我们不声明的话,如果开始的一个对象序列化时,会为我们自动生成一个版本,如果后面我们修改了此类,那么在反序列化的时候,会发生版本不一致的问题。所以一般我们会声明成一个定值,这样就能防止上述问题。我们可以把版本代码注释掉,运行一下反序列化结果如下:

Exception in thread "main" java.io.InvalidClassException: serializable.SerializableTest; local class incompatible: stream classdesc serialVersionUID = 4564223277371155727, local class serialVersionUID = 5130976784646098676
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at serializable.SerializableTest.deSerializable(SerializableTest.java:89)
    at serializable.SerializableTest.main(SerializableTest.java:60)
posted @ 2020-01-03 12:09  wanghq1994  阅读(167)  评论(0编辑  收藏  举报