java中类实现Serializable接口的原因_雪泪寒飞起来的博客-程序员宅基地

技术标签: java  序列化  

背景:一个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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dapeng1995/article/details/81449688

智能推荐

实战 Groovy: 用 Groovy 进行 Ant 脚本编程_SleepInDelphi的博客-程序员宅基地

Ant 和 Maven 两者在构建处理工具的世界中占统治地位。但是 XML 却凑巧是一种非常没有表现力的配置格式。在“实战 Groovy”这个新系列的第 2 期中,Andrew Glover 将介绍 Groovy 的生成器实用工具,这个工具能够极其容易地把 Groovy 与 Ant 和 Maven 结合在一起,形成更具表现力、更可控的构建。Ant 作为 Java 项目构建工具的普遍性和...

测验1: Python基本语法元素 (第1周)_菜鸟学飞ing去看世界的博客-程序员宅基地

1.Hello World的条件输出描述获得用户输入的一个整数,参考该整数值,打印输出"Hello World",要求:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬如果输入值是0,直接输出"Hello World"‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫...

surfacebook跑matlab,微软Surface book开坑:用TLC闪存,写入速度太渣_安徒生i的博客-程序员宅基地

微软的Surfacebook笔记本刚发布时惊艳了整个世界,一下子成了笔记本的终极代表,秒杀苹果Macbook Pro不是个事儿。但随着Surfacebook的上市,Surfacebook也开始被人吐槽了,那颗性能是苹果笔记本三倍的GPU并不是GTX 950M而是低端的GeForce 940M,现在SSD硬盘上也挖出坑来了,它能上1TB容量也不是没代价的,用的三星PM951硬盘竟然是TLC闪存的,速...

C语言程序设计中十全十美,21世纪高校计算机应用技术系列规划教材 C语言程序设计-潭浩强主编 林小茶编著.pdf..._十三周的博客-程序员宅基地

语言是一种通用的程序设计语言,它具有丰富的运算符和表达式,以及先进的控制结构和数据结构。 语言具有表达能力强、编译 目标文件质量高、语言简单灵活、容易移植及容易实现等优点。程序与程序设计语言程序随着计算机走入寻常百姓家, “程序 ”已经不再是计算机科学使用的专用词汇了。在 日常生活 中,我们其实在不断地编写程序并执行,只不过人们并没有明确地意识到而 已。举个例子,我们现在要用全 自动...

第6篇-JAVA面向对象Ⅱ_anonymous-system的博客-程序员宅基地

第6篇-JAVA面向对象Ⅱ 每篇一句 :敢于向黑暗宣战的人,心中必定充满光明初学心得: 面向对象 春暖花开(笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-05| JAVA面向对象 Ⅱ]目录导航第6篇-JAVA面向对象 目录导航JAVA面向对象三大特征面向对象 之 封装面向对象 之 继承面向对象 之 多态初学面向对象三大特征 难点 希望每一篇文章都能够对

Mybatis报错 java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符_胡渣叔叔的博客-程序员宅基地

将sql语句拿到数据库运行成功,项目启动一直报无效字符将sql 最后的 ;去掉就行

随便推点

php动态网址可以做seo么,动态URL会影响网站SEO排名吗_李敏哼马克的博客-程序员宅基地

动态URL会影响网站SEO排名吗事实上无论是动态URL,还是静态URL,都不会对SEO排名造成影响,搜索引擎能够收录所有符号的URL,包括一些特殊的符号,而且搜索引擎能够收录很长的URL,完全不用担心动态URL含有特殊符号而不会被收录,更不用担心动态URL过长而不能被收录,只要URL能够正常收录,就不会对SEO优化造成影响,URL只是搜索引擎索引的一个引导方向,不能决定SEO优化结果。换句话说UR...

NKOJ 4252 数三角形(乱搞)_Mogician_Evian的博客-程序员宅基地_425n.cn

P4252数三角形问题描述 刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决。给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色。现在,洁洁需要给这张图的多样性进行打分。一张图的多样性取决于它的同色和异色三角形的个数。具体来说,G 中每有一个三边颜色都互不同的三角形(异色三角形)可以得 3 分,每有一个三边颜色都相同的三角形(同色三角形)

kettle+kafka+mysql_Kettle-demo_速度发挥长处的博客-程序员宅基地

Kettle-demoETL是数据抽取(Extract)、清洗(Cleaning)、转换(Transform)、装载(Load)的过程。用户从数据源抽取出所需的数据,经过数据清洗和转换,最终形成所需的数据仓库,可用于进行数据统计分析,做商业决策等 。本项目使用开源ETL工具kettle实现一些常用的功能进行演示。查询和连接:包含数据流的查询、连接查询有关的组件。脚本:包含自定义脚本的使用,脚本可以...

linux 远程访问 ssh,Linux 之 实现ssh远程访问_Rita201907的博客-程序员宅基地

1、安装ssh$yuminstallopenssh-serveropenssh-clients2、启动ssh服务$sudo/etc/init.d/sshstart sshd.service或$sudo systemctl start3、指定登陆用户$ssh-lroot192.168.1.10或[email protected]、指定端口SSH默认使用的端口号是...

阿里云DevOps助理工程师认证学习笔记 2 - 需求管理和版本规划_蚂蚁码代码的博客-程序员宅基地

需求管理和版本规划 需求的定义: IEEE软件工程标准词汇表(97年)定义为: a.用户解决问题或达到目标所需的条件或权能; b.系统或系统部件要满足合同、标准、规范或其它正式规定文档所需具有的条件或权能; c.一种反映上述两点所描述的条件或权能的文档说明。 软件需求包括以下几个层次: a. 业务需求 b. 用户需求 c....

推荐文章

热门文章

相关标签