- 浏览: 55405 次
- 来自: 北京
最新评论
-
x10232:
3+3+4+4
impala学习总结 -
x10232:
一个房子里有椅子,椅子有腿和背,房子与椅子是什么关系,椅子与腿 ...
关联、组合、聚合、依赖关系比较
serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。
serialVersionUID有两种显示的生成方式:
一是默认的1L,比如:private static final long serialVersionUID = 1L;
二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
当一个类实现了Serializable接口,如果没有显示的定义serialVersionUID,Eclipse会提供相应的提醒。面对这种情况,我们只需要在Eclipse中点击类中warning图标一下,Eclipse就会 自动给定两种生成的方式。如果不想定义,在Eclipse的设置中也可以把它关掉的,设置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==> Potential programming problems
将Serializable class without serialVersionUID的warning改成ignore即可。
当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果Class文件(类名,变量名,方法明等)没有发生变化(修改或增减),就算再编译多次,serialVersionUID也不会变化的。有待证明
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
下面用代码说明一下serialVersionUID在应用中常见的几种情况。
(1)序列化实体类
(2)序列化功能:
(3)反序列化功能:
情况一:假设Person类序列化之后,从A端传输到B端,然后在B端进行反序列化。在序列化Person和反序列化Person的时候,A端和B端都需要存在一个相同的类。如果两处的serialVersionUID不一致,会产生什么错误呢?
【答案】可以利用上面的代码做个试验来验证:
先执行测试类SerialTest,生成序列化文件,代表A端序列化后的文件,然后修改serialVersion值,再执行测试类DeserialTest,代表B端使用不同serialVersion的类去反序列化,结果报错:
情况二:假设两处serialVersionUID一致,如果A端增加一个字段,然后序列化,而B端不变,然后反序列化,会是什么情况呢?
【答案】新增 public int age; 执行SerialTest,生成序列化文件,代表A端。删除 public int age,反序列化,代表B端,最后的结果为:执行序列化,反序列化正常,但是A端增加的字段丢失(被B端忽略)。
情况三:假设两处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?
【答案】序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。
情况四:假设两处serialVersionUID一致,如果B端增加一个字段,A端不变,会是什么情况呢?
验证过程如下:
先执行SerialTest,然后在实体类Person增加一个字段age,如下所示,再执行测试类DeserialTest.
相应的修改测试类DeserialTest,打印出age的值。
结果为:
Person Deserial Person: 1234 wang age: 0
说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值0。
最后通过下面的图片,总结一下上面的几种情况。
原文链接:http://swiftlet.net/archives/1268
附:官方文档
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
serialVersionUID有两种显示的生成方式:
一是默认的1L,比如:private static final long serialVersionUID = 1L;
二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
当一个类实现了Serializable接口,如果没有显示的定义serialVersionUID,Eclipse会提供相应的提醒。面对这种情况,我们只需要在Eclipse中点击类中warning图标一下,Eclipse就会 自动给定两种生成的方式。如果不想定义,在Eclipse的设置中也可以把它关掉的,设置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==> Potential programming problems
将Serializable class without serialVersionUID的warning改成ignore即可。
当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果Class文件(类名,变量名,方法明等)没有发生变化(修改或增减),就算再编译多次,serialVersionUID也不会变化的。有待证明
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
下面用代码说明一下serialVersionUID在应用中常见的几种情况。
(1)序列化实体类
import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 1234567890L; public int id; public String name; public Person(int id, String name) { this.id = id; this.name = name; } public String toString() { return "Person: " + id + " " + name; } }
(2)序列化功能:
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerialTest { public static void main(String[] args) throws IOException { Person person = new Person(1234, "wang"); System.out.println("Person Serial" + person); FileOutputStream fos = new FileOutputStream("Person.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(person); oos.flush(); oos.close(); } }
(3)反序列化功能:
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class DeserialTest { public static void main(String[] args) throws IOException, ClassNotFoundException { Person person; FileInputStream fis = new FileInputStream("Person.txt"); ObjectInputStream ois = new ObjectInputStream(fis); person = (Person) ois.readObject(); ois.close(); System.out.println("Person Deserial" + person); } }
情况一:假设Person类序列化之后,从A端传输到B端,然后在B端进行反序列化。在序列化Person和反序列化Person的时候,A端和B端都需要存在一个相同的类。如果两处的serialVersionUID不一致,会产生什么错误呢?
【答案】可以利用上面的代码做个试验来验证:
先执行测试类SerialTest,生成序列化文件,代表A端序列化后的文件,然后修改serialVersion值,再执行测试类DeserialTest,代表B端使用不同serialVersion的类去反序列化,结果报错:
Exception in thread "main" java.io.InvalidClassException: test.Person; local class incompatible: stream classdesc serialVersionUID = 1234567890, local class serialVersionUID = 123456789 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:560) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1580) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1493) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1729) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1326) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348) at test.DeserialTest.main(DeserialTest.java:15)
情况二:假设两处serialVersionUID一致,如果A端增加一个字段,然后序列化,而B端不变,然后反序列化,会是什么情况呢?
【答案】新增 public int age; 执行SerialTest,生成序列化文件,代表A端。删除 public int age,反序列化,代表B端,最后的结果为:执行序列化,反序列化正常,但是A端增加的字段丢失(被B端忽略)。
情况三:假设两处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?
【答案】序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。
情况四:假设两处serialVersionUID一致,如果B端增加一个字段,A端不变,会是什么情况呢?
验证过程如下:
先执行SerialTest,然后在实体类Person增加一个字段age,如下所示,再执行测试类DeserialTest.
import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 123456789L; public int id; public String name; public int age; public Person(int id, String name) { this.id = id; this.name = name; } public String toString() { return "Person: " + id + " " + name; } }
相应的修改测试类DeserialTest,打印出age的值。
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerialTest { public static void main(String[] args) throws IOException { Person person = new Person(1234, "wang"); System.out.println("Person Serial" + person + " age:" + person.age); FileOutputStream fos = new FileOutputStream("Person.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(person); oos.flush(); oos.close(); } }
结果为:
Person Deserial Person: 1234 wang age: 0
说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值0。
最后通过下面的图片,总结一下上面的几种情况。
原文链接:http://swiftlet.net/archives/1268
附:官方文档
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
发表评论
-
Java实现几种常见排序方法
2016-02-24 11:22 586package test.sort; import ... -
位图应用场合
2015-09-17 17:08 508位图主要用于快速检索关键字状态,通常要求关键字是一个连续的序 ... -
泛型使用注意事项
2015-09-17 09:06 520参数化类型可以引用一个原始类型的对象,编译报告警告,例 ... -
把整数排成最小的数
2015-08-27 15:51 536package test; import java.util ... -
Spring的注解配置与XML配置之间的比较
2015-08-08 21:00 4684注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 ... -
equals方法和hashCode方法
2015-08-01 10:38 637哈希表这个数据结构想 ... -
关联、组合、聚合、依赖关系比较
2015-07-29 23:46 1109类之间的关系 1. 种类 ... -
Java关键字final、static使用总结
2015-07-29 23:41 572一、final 根据程序上下文环境,Java关 ... -
Java对数组的复制
2015-07-27 22:22 716定义一个数组 int[] a={3,1,4,2,5}; i ... -
JAVA深复制(深克隆)与浅复制(浅克隆)
2015-07-27 16:50 7731.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变 ... -
JVM类加载器(双亲委托模型)
2015-07-25 21:11 1837JVM类加载器(双亲委托模型) (1)类加载器的父委托机制:优 ... -
深入理解Java对象序列化
2015-07-25 17:01 402关于Java序列化的文章早已是汗牛充栋了,本文是对我个人过往学 ... -
POI读取Excel时对cell中数据的判断
2015-07-24 10:12 4352Iterate over cells, with contro ... -
POI读取Excel时数据类型转换的问题
2015-07-24 09:44 70791. 数值类型处理 通过POI取出的数值默认都 ...
相关推荐
1.serialVersionUID-->适用于Java的序列化机制: 2.具体化序列化过程: 3.serialVersionUID有两种显示的生成方式:
代码中,我们定义了一个 Person 类,...需要注意的是,序列化和反序列化的类必须具有相同的 serialVersionUID,以确保对象的一致性。同时,为了避免序列化敏感信息,可以使用 transient 关键字标记不需要序列化的字段。
private static final long serialVersionUID = 1L; public XmlNode() { } public String tagName; public String tagValue; public String attList; public int level; public XmlNode parent; public...
private static final long serialVersionUID = 1L; private String fileName; // 文件名称 private long fileLength; // 文件长度 private byte[] fileContent; // 文件内容 public Message(){ } p
客户端提交两个String类型的参数,服务端返回一个对象类型。...public class Person implements Serializable { /** * */ private static final long serialVersionUID = -410186774891162281L;
java-lt 关于大数据的一些测试 idea 添加作者信息 File--> Settings--> Editor--> File and Code Templates-->...将 Serializable class without serialVersionUID 勾选 idea jihuoma #ssh 客户端 Termius
import java.io.Serializable; import java.util.List; public class PageBean<DUser> implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private List<DUser> list;/...
Class is Serializable, but doesn't define serialVersionUID 描述:类是可序列化的,但是没有定义serialVersionUID; 处理方式:自动生成serialVersionUID; Field only ever set to null 描述:Field一直被设置为...
2.接口和抽象类有什么区别 接口不能有方法实现,也就是说接口的方法都是抽象方法,但抽象类可以有方法实现。...序列化的实现一般是通过实现Serializable接口,并且会有一个serialVersionUID,这个ID叫做序列化ID
private static final long serialVersionUID = -5596241291862147220L; private int id; private String name; private int age; @Id public int getId() { return id; } public void setId(int id) { ...
ConcurrentHashMap继承了AbstractMap,实现了ConcurrentMap,Serializable接口,ConcurrentMap又实现了Map接口。ConcurrentHashMap是基于散列表实现的,存储的是Key/Value对,底层使用数组+链表+红黑树+CAS算法实现...
#Jersey-2 with Guice Persist一个项目,演示如何在Jersey2(JAX-RS)容器中使用JPA配置Google Guice。 该项目不使用Guice servlet模块或Guice持久... private static final long serialVersionUID = 366534908950086
private static final long serialVersionUID = 1L; 序列化是什么 内存中的数据对象只有转换为二进制流才能进行数据持久化和网络传输。 序列化:将数据对象转换为二进制的过程称之为序列化(Serialization) 反序列化...
/** * 图⽂类型 */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class NewArticle implements Serializable { private static final long serialVersionUID = ...
ProxyFactory.proxy 方法,生成接口的代理对象,直接调用方法客户端和服务器端的接口和实体类要一致,实体类必须是可以序列化的比如:定义Bean: public class DemoBean implements java.io.Serializable{ ...
private static final long serialVersionUID = 1945562032261336919L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } ...
16. private static final long serialVersionUID = 1L; 17. @Id 18. @Basic(optional = false) 19. @GeneratedValue(strategy = GenerationType.IDENTITY) 20. @Column(name = "id", nullable = false) 21. ...
codeceo 首页问答热门文章RSS订阅 文章首页 Java JavaScript ... iOS ...2018-07-25 分类:JAVA开发、编程开发、首页精华0人评论 来源:crossoverjie.top ...Map 这样的 Key Value 在软件开发中是非常经典的结构,常...