背景:一个java中的类只有实现了Serializable接口,它的对象才是可序列化的。如果要序列化某些类的对象,这些类就必须实现Serializable接口。Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。

为什么要进实现Serializable接口:为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来,这是java中的提供的保存对象状态的机制—序列化。

在什么情况下需要使用到Serializable接口呢?

  1、当想把的内存中的对象状态保存到一个文件中或者数据库中时候;

  2、当想用套接字在网络上传送对象的时候;

  3、当想通过RMI传输对象的时候;

  

serialVersionUID

serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。显式地定义serialVersionUID有两种用途:

  a. 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;

  b. 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

代码实现:

在这里 定义一个实现了Serializable接口的Person类

import java.io.Serializable;

public class Person implements Serializable {
private int id;
private String 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;
}
}

再定义一个SerializationUtils类来模拟 序列化和反序列化的过程

import java.io.*;

public class SerializationUtils {
private static String FILE_NAME = "f:/obj";
//序列化 写的过程
public static void write(Serializable s){
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(FILE_NAME));
objectOutputStream.writeObject(s);
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} //反序列化 读的过程
public static Object read(){
Object obj=null;
// 反序列化
try {
ObjectInput input = new ObjectInputStream(new FileInputStream(FILE_NAME));
obj = input.readObject();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}

测试函数

import com.txp.SerializationUtils;
import org.junit.Test; public class testSerializable {
@Test
public void testWrite(){
Person person=new Person();
person.setId(1);
person.setName("张丹");
SerializationUtils.write(person);
} @Test
public void testRead(){
Person p = (Person) SerializationUtils.read();
System.out.println(p.getName());
}
}

先运行testWrite()实现序列化持久化,再运行testRead()实现反序列化读出数据 ,这一次的Person类中没有给定serialVersionUID,结果会输出‘张丹’。

如果此时给Person类加一个属性 age,运行testRead(),会抛出会抛出 java.io.InvalidClassException异常。因为JVM在反序列化时,会比较数据流中的serialVersionUID与类的serialVersionUID是否相同,如果相同,则认为类没有发生改变,可以把数据流load为实例对象;如果不相同,对不起,JVM会抛异常InvalidClassException,这是JVM一个很好的一个校验机制,确保类的一致性。

但是如果显式给定serialVersionUID(而隐式声明则是我不声明,编译器在编译的时候帮我生成。),即是 private static final long serialVersionUID = XXL;,修改Person类如下:

public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String 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;
}
}

再进行同样的操作过程,则不会抛出异常,会打印出结果。但是最好不要这样操作,要在类修改后,先序列化,再但序列化。确保类的前后一致性。

参考文章:

https://www.cnblogs.com/yoohot/p/6019767.html

https://blog.csdn.net/jaryle/article/details/52598296

http://www.cnblogs.com/DreamDrive/p/5412931.html

java中类实现Serializable接口的原因的更多相关文章

  1. Java中的Serializable接口和transient关键字

    Java中的Serializable接口和transient关键字 Table of Contents 1. 向memcached中放数据时遇到NotSerializableException异常 2 ...

  2. Java 的序列化Serializable接口介绍及应用

    常看到类中有一串很长的 如 private static final long serialVersionUID = -4667619549931154146L;的数字声明.这些其实是对此类进行序列化 ...

  3. Java中的Serializable接口transient关键字,及字节、字符、对象IO

    1.什么是序列化和反序列化Serialization是一种将对象转为为字节流的过程:deserialization是将字节流恢复为对象的过程. 2.什么情况下需要序列化a)当你想把的内存中的对象保存到 ...

  4. java中的Serializable接口的作用

    实现java.io.Serializable 接口的类是可序列化的.没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化. 序列化类的所有子类本身都是可序列化的.这个序列化接口没有任何方法和域, ...

  5. java中的Serializable接口

    实现java.io.Serializable 接口的类是可序列化的.没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化. 序列化类的所有子类本身都是可序列化的.这个序列化接口没有任何方法和域, ...

  6. Idea中类实现Serializable接口 引入 serialVersionUID

    idea实现Serializable接口,然后打出serialVersionUID的办法 setting>editor>Inspection>Java>Serializatio ...

  7. Java中类继承、接口实现的一些细节(长期更新)

    前言 在Java中,子类继承父类,类实现接口是属于常识性的内容了,作为一个Java程序员应该也比较熟悉.不过子类继承父类,类实现接口中还是有一些小细节值得注意一下,本文就从个人工作.学习中入手,总结一 ...

  8. Java中类继承、接口实现的一些要注意的细节问题

    1.接口A和接口B有相同的方法,只是返回值不同,则实现类不能同时实现这两个接口中的方法. 接口A有void C()方法,接口B有int C()方法,则无法同时实现这两个接口. Java为了弥补类单继承 ...

  9. Java中实现Serializable接口为什么要声明serialVersionUID?

    什么情况下需要修改serialVersionUID 的值?      序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化 ...

随机推荐

  1. sed 替换命令使用

    输入文件不会被修改,sed 只在模式空间中执行替换命令,然后输出模式空间的内容.文本文件 employee.txt 101,John Doe,CEO 102,Jason Smith,IT Manage ...

  2. 修改 oracle 数据库的 sys 账号密码,ERROR at line 1: ORA-01034: ORACLE not available

    挺久没有登录的 oracle 数据库,因为公司要求加固密码,登录后修改失败 1.启动数据库的同时启动控制文件.数据文件,提示:cannot mount database in EXCLUSIVE mo ...

  3. 如何减小微信小程序代码包大小

    原作于:https://captnotes.com/how_to_reduce_package_size_of_weapp 这两天被小程序代码包大小暴涨的问题困扰了挺久.简单说说怎么回事吧,就是之前好 ...

  4. 我罗斯方块最终篇(Block类)

    负责的任务 完善Block类的相关函数及变量: 对Block类中函数进行调整改进,并于其他人负责的类相互配合: 对Block类的函数功能进行调试: github项目地址. 效果图 具体可见总篇,一下仅 ...

  5. 13.Fibonacci数

    描述 无穷数列1,1,2,3,5,8,13,21,34,55...称为Fibonacci数列,它可以递归地定义为 F(n)=1 ...........(n=1或n=2) F(n)=F(n-1)+F(n ...

  6. Effective C++ 总结笔记(五)

    六.继承与面向对象设计 32.确定你的public继承塑模出is-a关系 public继承意味着is-a.适用于base class身上的每一件事情也一定适用于derived class身上.每一个d ...

  7. JVM-学习笔记持续更新

    1.Java虚拟机的基本结构 (1)类加载子系统与方法区: 类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放在一块称为方法区的内存空间.除了类的信息外,方法区中可能还会存放运行 ...

  8. [bzoj5415]归程

    首先肯定要预处理出每一个点到1的最短路(别写spfa) 然后以海拔为边权,建一棵kruskal重构树 用倍增找到vi最后一个小于pi的祖先,然后在子树中取min(预处理) 1 #include< ...

  9. [bzoj1635]最高的牛

    初始如果没有限制,很显然每一头牛高度都是h当只有一个限制,让h[a]到h[b]的高度都减1即可容易发现两个限制不会相交(否则必然矛盾),只会包含或相离,因此没有影响,直接差分/线段树即可(注意:1.不 ...

  10. [loj3246]Cave Paintings

    题中所给的判定条件似乎比较神奇,那么用严谨的话来说就是对于两个格子(x,y)和(x',y'),如果满足:1.$x\le x'$:2.从(x,y)通过x,x+1,--,n行,允许向四个方向走,不允许经过 ...