Java 重新理解Serializable

  • Java 序列化:指的是将Java对象通过流的方式写到磁盘上将其保存起来。

最初是为了支持RMI(Remote Method Invocation)远程方法调用,它可以实现其它计算机访问该对象就像自己的计算机访问该对象那么的简单,还有就是JavaBean这种对象在设计阶段启动时的状态配置。一般将对象或者异常输出到文件作持久化或者通过网络传输到其它计算机进行处理。

  • Java反序列化:序列化的逆过程,将序列化到文件中的内容反序列化成对象。

程序实现

class Student implements Serializable {
    public static int week;
    private String name;
    private int age;
    // 使用transient关键字后不会序列化该字段
    private transient String homeWork;

    public Student(String name, int age, String homeWork, int weekday) {
        this.name = name;
        this.age = age;
        this.homeWork = homeWork;
        week = weekday;
    }

    @Override
    public String toString() {
        return "Student [" + "name=" + name + ", "
                + "age=" + age + ", homeWork=" + homeWork + ", "
                + "static week=" + week + "]";
    }

}

private static void serializeStudent() throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/student"));
    oos.writeObject(new Student("小明", 10, "做数学题", 2));
    oos.close();
}

private static Student deserializeStudent() throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/student"));
    Student stu = (Student) ois.readObject();
    ois.close();
    return stu;
}

第一次测试

public static void main(String[] args) throws IOException, ClassNotFoundException {
    serializeStudent();
    System.out.println(deserializeStudent());//Student [name=小明, age=10, homeWork=null, static week=2]
}

嗯。。看似很完美,先别急,接着第二次测试。。

public static void main(String[] args) throws IOException, ClassNotFoundException {
    //serializeStudent();
    //因为之前已经序列化并且保存到磁盘了,现在直接进行反序列化操作
    System.out.println(deserializeStudent());//Student [name=小明, age=10, homeWork=null, static week=0]
}

看到这里,有没有发觉程序结果发生了小小的变化?没错那就是week这个静态变量。说到这里可能有人就有疑问了,那么之前的那个week怎么就没错呢?这个其实是因为static变量在经类加载器加载过后会永驻内存,事实上不管你是否进行序列化和反序列化它都是那个值,也就是2。但第二次测试后,Jvm重新运行当然要重新加载Student了,因为序列化并不会对static起作用,所以week这个变量并没有保存,那么week自然就是默认值,也就是0,

防止序列化和反序列化,当调用writeObject(Object obj)方法时会检查该对象是否具有writeObject()和readObject()方法如果有,则通过反射进行调用。

//防止序列化
private void writeObject(ObjectOutputStream os )throws IOException {
    throw new RuntimeException("");
}
//防止反序列化
private void readObject(ObjectInputStream in) throws IOException {
    throw new RuntimeException();
}

你可能感兴趣的:(Java 重新理解Serializable)