众所周知,当某class实现了Serializable接口后,由此class构建出的对象将具备序列化的能力,而Serializable这个接口中没有任何需要实现的方法,所以这个接口的作用仅仅是作为一个标记,告诉虚拟机,具有这个标记的对象,是可以被序列化的,而没有这个标记的则不要序列化。所以,虚拟机应该是可以将任何对象序列化的,只不过是它遵守了一个“道德“规范,仅序列化那些被允许可以序列化的。那为什么不是所有的对象都是可序列化的呢?我想也许是基于安全性的考量吧。
序列化的一般过程是:
- 在虚拟机A中,构造了class AClass的对象AObject
- 将AObject序列化写入到文件ObjectFile中
- 在虚拟机B中,读取文件ObjectFile
- 根据AClass和读取进来的byte[],构造虚拟机B中的AClass的对象BObject
这里面,不好理解的事情是在第四步中,如果虚拟机B仅有AObject的数据,并不足以构造出BObject,它必须还需要有AClass的信息。也就是说, 序列化,仅仅是把对象以二进制的形式写入到了文件之中,但是这些二进制该组织成什么样的一个东西,却并不能说明,所以还需要AClass的类型信息,这就 如同交给了你一大堆的机器零件,还需要你拥有一本组装说明书,你才能把这些零件组装成一架波音747。:)。也就是说,序列化的仅仅是Object,而没有同时把这个Object所依赖的所有class一并序列化过去。那为什么不这么做呢?也许和ClassLoader有关?又和安全性有关?
在实现了Serializable接口的class中,需要声明一个long serialVersionUID,用来标明当前class的版本号:
- 如果在序列化写时的版本号和序列化读时的版本号,不一致,将会有异常:
java.io.InvalidClassException:
local class incompatible: stream classdesc serialVersionUID = …, local class serialVersionUID = … - 那如果在class中不声明这个属性呢?那结果可以就会变得比较诡异了:
- 在序列化写的时候,虚拟机A会为它计算出一个serialVersionUID,计算的方法是依据class的信息,再具体我也不清楚了。
- 在序列化读的时候,虚拟机B也会为class计算出一个serialVersionUID,然后做比较。
- 那么如果两个虚拟机是不同类型的虚拟机,那么计算方法可能就不一样了,于是即使相同的class,serialVersionUID也可能会不同,不同的class的,理论上来说,也存在serialVersionUID相同的可能性,所以,serialVersionUID尽量由我们自己来指定,而不要由虚拟机来计算。
- 那如果serialVersionUID一致,而class发生了变化呢?
- 如果虚拟机A中的AClass有一个属性,而虚拟机B中的AClass,没有这个属性,那么这个属性将被忽略,而不会有异常。
- 如果虚拟机A中的AClass没有的属性,而在虚拟机B中多出来的属性,那么这个属性将被赋予一个缺省值,而不会有异常。
- 如果虚拟机A中的AClass有一个属性,在虚拟机B中的AClass也有这个属性,但这个属性的类型变了,比如说int变成了long,抑或其他的变化,将会有异常:
java.io.InvalidClassException:
incompatible types for field …
经过序列化而产生的异常都是 java.io.InvalidClassException,不会产生java.lang.ClassCastException,两者还是有比较大的区别的,从名字上就可以看得出来。
我自己遇到的问题是:local class incompatible: stream classdesc serialVersionUID = 4379444343007238900, local class serialVersionUID = -4347374884104808421
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
解决办法是去除所有Eclipse自动生成的serialVersionUID,当去除所有的serialVersionUID 后还出现以上问题,重启tomcat就好了
相关推荐
1.serialVersionUID-->适用于Java的序列化机制: 2.具体化序列化过程: 3.serialVersionUID有两种显示的生成方式:
代码中,我们定义了一个 Person 类,...需要注意的是,序列化和反序列化的类必须具有相同的 serialVersionUID,以确保对象的一致性。同时,为了避免序列化敏感信息,可以使用 transient 关键字标记不需要序列化的字段。
java-lt 关于大数据的一些测试 idea 添加作者信息 File--> Settings--> Editor--> File and Code Templates-->...将 Serializable class without serialVersionUID 勾选 idea jihuoma #ssh 客户端 Termius
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;
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 在软件开发中是非常经典的结构,常...