Serializable and serialVersionUID

如果某个 class implements Serializable,Eclipse 会提示生成 serialVersionUID ,多数情况下,我都选择是。可这个东西到底是什么呢?

package com.home.demo;

import java.io.Serializable;

public class Item implements Serializable {

	private static final long serialVersionUID = 1L;

	private int data;

    public Item (int data) {
        this.data = data;
    }

    public int getData() {
        return data;
    }

}

Eclipse 再次提醒我要有serialVersionUID 。 好吧,既然是测试,给他个值1。

写一个测试类,试试 serialize and deserialize  Item

package com.home.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class UIDTest {

	public void save2Disk(String fileName) throws IOException{
	File file = new File(fileName);
        FileOutputStream fos = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //set value to 101
        Item serializeMe = new Item(101); 
        oos.writeObject(serializeMe);
        oos.close();
        System.out.println("done!");
	}

	public void readFromDisk(String fileName) throws ClassNotFoundException, IOException{
	FileInputStream fis = new FileInputStream(fileName);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Item dto = (Item) ois.readObject();
        System.out.println("data : " + dto.getData());
        ois.close();
	}

	/**
	 * @param args
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) {
		UIDTest test = new UIDTest();
		String name = "D:/out.dat";
		try{
			// write file
			//test.save2Disk(name);   //--1

			test.readFromDisk(name);  // --2
		}catch(Exception e){
			e.printStackTrace();
		}
     
	}

}

运行结果

101

完全正确!

看看D盘,有个文件out.dat. 关闭写文件,直接读取 out.dat

运行结果

101

试试把 serialVersionUID = 2L

private static final long serialVersionUID = 2L;

再运行

java.io.InvalidClassException: com.home.demo.Item; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

噢。。。。 出错了!

根据 Java document,

Serialization is for serializing instances, not classes. Static fields (methods are irrelevant since they are part of the class definition so they aren‘t serialized) will be reinitialized to whatever value they are set to when the class is loaded.

根据这个说法,Item不可能知道  serialVersionUID  的值,为什么会报错?

继续看文档!

好吧 serialVersionUID  属于例外,这个值的确“get serialized”.

ObjectOutputStream writes every time the value ofserialVersionUID to the output stream.

ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException. Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.

假如你在机器A上serialize 了数据,然后送到B机器上deserialize ,需要一定的信息来帮忙确定数据的正确性。serialVersionUID  就是用于干这个活的。所以,Eclipse建议我们使用的serialVersionUID ,可以对serialization进行最简单的检验和控制。

如何正确使用 serialVersionUID  ?

What you should do is to change serialVersionUID (for example increase it by 1 or make your IDE generate automatically a new value) every time there is some change in the definition of data stored in the class. For example if you change data types, variable names or add new data – hence every time you want to have ‘backward incompatibility’ for deserialization.

Reference

http://stackoverflow.com/questions/6429462/java-static-serialization-rules

http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

http://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it

http://www.javablogging.com/what-is-serialversionuid/

http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/

时间: 2024-10-19 05:26:54

Serializable and serialVersionUID的相关文章

关于Serializable的serialVersionUID

在实现了Serializable接口的class中,需要声明一个long serialVersionUID,用来标明当前class的版本号,但很多人在编程时,总是不原意去声明这个serialVersionUID,又JVM自己来生成.下面来看看serialVersionUID的作用: 1.如果在序列化写 时的版本号和序列化读 时的版本号,不一致,将会有异常:java.io.InvalidClassException:local class incompatible: stream classdes

java.io.Serializable中serialVersionUID的作用

把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中

Serializable资料整理

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC" } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; min-height: 17.0px } span.s1 { font: 12.0px Helvetica } 1. 序列化 简单的说就是为了保存 内存中各种对象的状态(是实例变量,不是方法),并

Arrays源码分析

package java.util; import java.lang.reflect.Array; import java.util.concurrent.ForkJoinPool; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.DoubleBinaryOperator; import java.util.function.IntBi

[ 转 ]编写高质量代码:改善Java程序的151个建议

记得3年前刚到公司,同桌同事见我无事可做就借我看<编写高质量代码:改善Java程序的151个建议>这本书,当时看了几页没上心就没研究了.到上个月在公司偶然看到,于是乎又找来看看,我的天,真是非常多的干货,对于我这种静不下心的人真是帮助莫大呀. 看完整本书,也记了不少笔记,我就分享一部分个人觉得有意义的内容,也为了方便以后自己温习. --警惕自增陷阱 i++表示先赋值后自增,而++i表示先自增后赋值.下面的代码返回结果为0,因为lastAdd++有返回值,而返回值是自增前的值(在自增前变量的原始

JSON字符串转JavaBean,net.sf.ezmorph.bean.MorphDynaBean cannot be cast to ……

在json字符串转java bean时,一般的对象,可以直接转,如:一个学生类,属性有姓名.年龄等 public class Student implements java.io.Serializable{ /** * @Fields serialVersionUID : TODO */ private static final long serialVersionUID = -1943961352036134112L; private String sname; private Integer

学生管理系统----学生封装类

Student.java: /** * @Title:Student.java * @Package:com.you.student.system.model * @Description:学生信息封装类 * @author:Youhaidong(游海东) * @date:2014-6-16 下午11:00:22 * @version V1.0 */ package com.you.student.system.model; import java.io.Serializable; import

SpringBoot实践 - SpringBoot+mysql

关于springBoot是个神马东西以及优缺点,请自行搜索了解. LZ看到很多关于SpringBoot的Demo,单看一篇总是没法整合SpringBoot与Mysql.没法子,还是自己操刀来一发为妙. 本文将叙述关于SpringBoot与mysql整合实践. 1.Eclipse 整合SpringBoot插件.(此步骤非常耗时,LZ本身尝试了多次.请在网络环境优情况下下进行操作) a.Eclipse 安装STS插件: eclipse->help->Eclipse Marketplace b.检测

JdkDynamicAopProxy源码

JdkDynamicAopProxy是通过接口实现动态代理类,主要方法是getProxy(ClassLoader classLoader), 代理类生成之后再调用目标方法时就会调用invoke方法. package org.springframework.aop.framework; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; i