Serializable-源码分析

Posted 爱跑步的星仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Serializable-源码分析相关的知识,希望对你有一定的参考价值。

package java.io;
public interface Serializable {
}

代码很简单,功能也很简单,对象通过这个接口来实现序列化和反序列的。下面来看看小例子。

import java.io.Serializable;
public class Person implements Serializable{
    private String name;
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "姓名:"+this.name +" ;年龄:" + this.age;
    }
}

这是最常见的bean,但是Eclipse有提示:The serializable class Person does not declare a static final serialVersionUID field of type long;意思就是让你添加一个静态的long类型的常量serialVersionUID。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test{
    @org.junit.Test
    public void test(){
        Person person = new Person();
        person.setName("Tom");
        person.setAge(24);
        writeIntoFile(person);
        readFromFile();
    }
    //序列化
    public static void writeIntoFile(Serializable object){
        ObjectOutputStream out = null;
        try {
            out = new ObjectOutputStream(new FileOutputStream("111.txt"));
            out.writeObject(object);
            out.write(2);
            out.flush();
            System.out.println("序列化成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //反序列化
    public static void readFromFile(){
        ObjectInputStream in = null;
        try {
            in = new ObjectInputStream(new FileInputStream("111.txt"));
            Person person =(Person)in.readObject();
            System.out.println("反序列化成功");
            System.out.println(person.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

结果是成功的:

其实如果不添加serialVersionUID,那么Eclipse在会根据这个类的结构生成一个hash值,然后将这个值作为serialVersionUID。(大家可以做实验,在不添加serialVersionUID情况,反序列化换之前修改bean对象,看结果是否报错)

试验步骤:

1、序列化User对象的时候,先不要添加serialVersionUID。

2、然后给Person对象添加serialVersionUID = 1000L,这个值随意。

3、开始对新添加的Person对象,进行反序列化。

结果报错 :java.io.InvalidClassException: object.testPackage.Person; local class incompatible: stream classdesc serialVersionUID = -5751053222744082002, local class serialVersionUID = 1000

小结:序列化时,系统会把序列化的类的serialVersionUID写入到序列化文件中(猜的),当反序列化时,系统会去检测文件中的serialVersionUID,如果类中的serialVersionUID值和文件的serialVersionUID值一致,那么就可以反序列化成功,反之失败。

 

以上是关于Serializable-源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Java 序列化和反序列化Serializable 源码分析 - 1

Java 序列化和反序列化Serializable 源码分析 - 2

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

String源码分析