本文为原创文章,欢迎转载,但请注明出处http://www.cnblogs.com/yexiubiao/p/5014015.html,未在文章页面明显位置给出原文连接的,将保留追究法律责任的权利。

通过java的ObjectOutputStream、ObjectInputStream类能对实现了Serializable接口的对象实现序列化与反序列化,如下

import java.io.Serializable;

import com.alibaba.fastjson.JSON;

public class Person implements Serializable{
private static final long serialVersionUID = 1L; private int id;
private String name; public Person() {
super();
} public Person(int id, String name) {
super();
this.id = id;
this.name = name;
} public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public String toString() {
          // 这里偷懒用了Fastjson
return JSON.toJSONString(this);
}
}

  

序列化(写入对象):

反序列化(读取对象)

通过这样就能把一个对象存入磁盘里,并且能读取到内存里

以上是Serializable的基本用法,接下来介绍一些使用中的小细节(关于以下出现的术语,保存对象与序列化,读取对象与反序列化都分别是同一个意思)。

1,将对象序列化到本地后,对类进行修改,增加或减少字段(成员变量)或交换字段位置,然后反序列化之前保存的对象,都不会报错。

例如去掉id字段并增加newValue字段:

此时能正常读取之前序列化的对象(newValue字段因为值是null,这里默认不展示):

2,改变serialVersionUID值后,读取时发生异常

 java.io.InvalidClassException: com.ye.test.model.Movie; Incompatible class (SUID): com.ye.test.model.Movie: static final long serialVersionUID =1L; but expected com.ye.test.model.Movie: static final long serialVersionUID =2L;
因为serialVersionUID值改变后,类定义的版本变化了,所以读取老版本对象将可能不兼容新对象,因此系统抛出异常
读取为null:
 
3,保存的时候对象有serialVersionUID,然后删除这个字段,再次读取
则读取时serialVersionUID会被赋值一个自动生成的值

这个值根据类的成员变量方法定义等算出,增减成员变量或者增减方法都会导致这个值的改变
但是如果增加空格,交换成员变量位置等都不会导致这个值被改变
java.io.InvalidClassException: com.ye.test.model.Movie; Incompatible class (SUID): com.ye.test.model.Movie: static final long serialVersionUID =1L; but expected com.ye.test.model.Movie: static final long serialVersionUID =-6926675519878447654L;
也就是说,如果我们的Person类没有声明serialVersionUID变量,则以后这个类只要涉及到增减成员变量或者增减方法都会导致读取对象时不兼容。当然方法位置的调整不会影响。
 
4,如果先序列化保存一个对象到磁盘,然后修改这个类的定义,将其继承至一个基类(基类没有实现Serializable接口),则会报错

 java.io.InvalidClassException: com.ye.test.model.BaseMovie; IllegalAccessException
at java.io.ObjectStreamClass.resolveConstructorClass(ObjectStreamClass.java:692)
如果基类实现了Serializable接口,则能正常读取
 
5,如果基类已经实现了Serializable接口,则子类无需再次实现(当然子类再次实现也没关系)
 
6,父类的serialVersionUID成员变量对子类没有影响,即使他是public的,所以反序列化时能不能兼容只会跟子类的serialVersionUID对象数值相关。
也就是说开发中如果我们定义的类已经修改,需要告诉系统我们的类已经不再兼容老版本,则需要修改子类的serialVersionUID版本号而不是父类。
 
7,如果子类实现Serializable接口,父类没有实现,则只可以执行序列化,不能执行反序列化,执行反序列化时报错信息同4
 
总结:
1,如果存在继承关系,则只需在基类实现Serializable接口即可
2,serialVersionUID变量需在子类定义,父类定义没有意义(父类定义serialVersionUID用来消除编译警告信息也没关系)
3,如果没有定义serialVersionUID变量,则系统在保存或读取时会根据类结构自动算出一个值赋予serialVersionUID,如果类结构没有变化,那么这个值则是固定的,所以还是尽量使用自定义的值比较便于维护。
4,如果需求变更导致类结构调整,那么如果需要继续读取老版本对象的话, 则不要修改serialVersionUID的版本号,如果需要使用全新的数据而抛弃之前保存在磁盘里的对象,则修改serialVersionUID版本号,系统会默认读取为null。相当于之前没有保存过。
 
最后附上demo,有兴趣的话可以自己测试下。

Java里Serializable的那些事的更多相关文章

  1. Java你可能不知道的事(3)HashMap

    概述 HashMap对于做Java的小伙伴来说太熟悉了.估计你们每天都在使用它.它为什么叫做HashMap?它的内部是怎么实现的呢?为什么我们使用的时候很多情况都是用String作为它的key呢?带着 ...

  2. java你可能不知道的事(2)--堆和栈

    在java语言的学习和使用当中你可能已经了解或者知道堆和栈,但是你可能没有完全的理解它们.今天我们就一起来学习堆.栈的特点以及它们的区别.认识了这个之后,你可能对java有更深的理解. Java堆内存 ...

  3. java中serializable

    java中serializable是一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的.因此如果要序列化某些类的对象,这些类就必须实现Serializable接 ...

  4. Java里的IO流里的 ObjectInputStream 的读取\写入!

    各位好!!我又来了!!今天遇见了一个小问题!! IO流里的对象读取总是出错!各种报错!!神烦啊!!百思不得其解啊!然后就上网百度!找了好久终于让我找到了!下面就让我来说一说! 当你用IO流里的对象流写 ...

  5. java基础---->Serializable的使用

    本次讲解中我们建立一个Java的项目去体会一下序列化Serializable的使用,序列化的原理以及序列化的自定义请参见我的另外一篇博客(java高级---->Serializable序列化的源 ...

  6. java你可能不知道的事(2)--堆和栈<转>

    在java语言的学习和使用当中你可能已经了解或者知道堆和栈,但是你可能没有完全的理解它们.今天我们就一起来学习堆.栈的特点以及它们的区别.认识了这个之后,你可能对java有更深的理解. Java堆内存 ...

  7. Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,seria ...

  8. Java 序列化Serializable具体解释(附具体样例)

    Java 序列化Serializable具体解释(附具体样例) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描写叙述的过程:反序列化deserializa ...

  9. [转]Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

    原文地址:https://blog.csdn.net/qq_27093465/article/details/78544505 遇到这个 Java Serializable 序列化这个接口,我们可能会 ...

随机推荐

  1. Thread1:EXC_BAD_ACCESS 错误

    描述:野指针,在对象被释放之后又调用了该对象 场景:在某个UIVIewController释放之后有调用了该Controller的某些方法. 由于项目需求需要监控WebView的滚动,所以在控制器中给 ...

  2. 请求网络get

    package com.baidu.net; import java.io.IOException; import org.apache.http.HttpEntity;import org.apac ...

  3. Joomla及其类似软件的说明分析

    Joomla不单单是一款免费的软件,还是在国外相当知名的及内容管理.web开发及手机应用开发等为一体的一套系统.Joomla是使用PHP语言加上MySQL数据库所开发的软件系统,可以在Linux. W ...

  4. 输入输出流(IO)

    输入输出流(IO)文件(File)java.io.File用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录.File类只用于表示文件(目录)的信息(名称.大小等), ...

  5. Linux下高cpu解决方案(转载)

    昨天搞定了一个十万火急的issue,客户抱怨产品升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,弄得我们 R&D压力很大,解决这个issue的任务分给了我,客 ...

  6. Codeforces Round #169 (Div. 2)

    A. Lunch Rush 模拟. B. Little Girl and Game 因为可以打乱顺序,所以只关心每种数字打奇偶性. 若一开始就是回文,即奇数字母为0或1种,则先手获胜. 若奇数字母大于 ...

  7. 《C与指针》第十五章练习

    本章例程 15.1打开和关闭文件 #include <stdlib.h> #include <stdio.h> int main(int ac, char **av) { in ...

  8. AT指令(转)

    资料来自网络 附录AT指令简编一. 一般命令1.AT+CGMI 给出模块厂商的标识.2.AT+CGMM 获得模块标识.这个命令用来得到支持的频带(GSM 900,DCS 1800 或PCS 1900) ...

  9. Singly Linked List

    Singly Linked List Singly linked list storage structure:typedef struct Node{ ElemType data; struct N ...

  10. multithreading - Reader/Writer Locks in C++

    You Only Need To Note This: only 1 single thread can acquire an upgrade_lock at one time. others are ...