原创转载请注明出处:http://agilestyle.iteye.com/blog/2301301
先看一个简单的例子
package org.fool.test; import java.io.Serializable; public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private long id; private String username; private String password; public User() { } public User(long id, String username, String password) { this.id = id; this.username = username; this.password = password; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + "]"; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
这里先创建一个User对象,序列化UID为1L
package org.fool.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableTest { public static void main(String[] args) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(new File("serial.txt")))); oos.writeObject(new User(1L, "hello", "world")); oos.close(); ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("serial.txt")))); User user = (User) ois.readObject(); System.out.println(user); ois.close(); } }
接着使用IO进行读写,查看输出
User [id=1, username=hello, password=world]
本地工程下面生成了serial.txt文件,然后将User对象的序列化UID改为2L
public class User implements Serializable { /** * */ private static final long serialVersionUID = 2L; private long id; private String username; private String password; ......
同时注释掉原先的IO写操作,只进行读操作
public class SerializableTest { public static void main(String[] args) throws Exception { //ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(new File("serial.txt")))); //oos.writeObject(new User(1L, "hello", "world")); //oos.close(); ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("serial.txt")))); User user = (User) ois.readObject(); System.out.println(user); ois.close(); } }
查看输出
Exception in thread "main" java.io.InvalidClassException: org.fool.test.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at org.fool.test.SerializableTest.main(SerializableTest.java:18)
Java通过一个名为UID(stream unique identifier)来控制,这个UID是隐式的,它通过类名,方法名等诸多因素经过计算而得,理论上是一一映射的关系,也就是唯一的。如果UID不一样的话,就无法实现反序列化了,并且将会得到InvalidClassException。这就是通常项目中版本升级会遇到的问题,很有可能缓存或者数据库的数据是以1L的版本写入,之后由于项目版本升级,UID变为了2L,在2L的基础上进行读操作,就会抛出这个异常,也就是序列化兼容性问题,解决的办法就是将UID版本统一,并且将原先缓存或数据库的数据清空,同时以当前最新的UID版本重新写入。
相关推荐
2. 自动生成serialVersionUID:如果没有显式定义serialVersionUID,Java序列化机制会根据Class自动生成一个serialVersionUID。 3. 使用IDE生成serialVersionUID:在Eclipse中,可以使用IDE生成serialVersionUID,...
为了防止这种情况,可以使用`ObjectStreamClass.lookup(Class)`检查类是否可信任,或者使用`ObjectInputStream.resolveClass(ClassDesc)`和`resolveProxyClass(String[])`来控制反序列化过程。 总结,Java序列化是...
1. **序列化与反序列化**:Classdesc可以方便地将对象的状态转换为二进制流,从而实现对象的持久化存储或网络传输。 2. **动态配置**:允许程序根据配置文件在运行时动态创建和配置对象,增强了系统的灵活性。 3. ...
`UPDATE`语句用于修改已有数据,如`UPDATE classinfo SET classdesc='good' WHERE classid='3班'`将"3班"的班级描述更改为"good"。`DELETE FROM`则用于删除数据,`DELETE FROM studinfo WHERE studno='2011003'`将...
对象类型可能是代理类(proxy class),如TC_OBJECT标识的TC_PROXYCLASSDESC,表示实现了两个接口:java.rmi.Remote和ICalc。接口名分别以UTF-8编码存储,表明该对象具备远程调用的能力。接着,类描述(classDesc)...
2. LibNumberClasses():返回插件包含的类数量。 3. LibClassDesc():根据索引返回特定的ClassDesc指针,用于创建插件对象。 4. LibVersion():确保插件与3dsmax版本兼容。 导出函数需要使用`__declspec(dllexport)...
1. **导出函数**: 所有3ds Max插件都需要一个导出函数,例如`FRExtension`或`FactoryClass`,这是3ds Max加载插件时调用的第一个函数。这个函数会告诉3ds Max关于插件的信息,如插件类型、版本和名称。 2. **类注册...
源码分为"Day 1"和"Day 2"两个部分,可能代表了学习或开发过程中的两个阶段。让我们逐一解析这两个阶段可能包含的知识点: 1. **3ds Max SDK基础知识**:首先,你需要理解3ds Max SDK的基础概念,包括MaxScript、...
1. **基础概念** - **插件开发**:3dsmax 2010 SDK支持C++和MAXScript两种方式开发插件,通过SDK中的API接口,开发者可以创建新的对象类型、修改现有对象的行为或实现新的功能。 - **MAXScript**:这是3ds Max的...
| java.lang.Class | ::javax::rmi::CORBA::ClassDesc | 在某些情况下,例如java.lang.String,如果将其声明为final static,则可以直接映射为IDL中的wstring类型;而在其他情况下,它将被映射为值类型`CORBA::...
有些类可以作为自己的符号引用(例如 String),而对于可链接常量,定义了一系列符号引用类型(ClassDesc、MethodTypeDesc、MethodHandleDesc 和 DynamicConstantDesc),它们包含描述这些常量的 nominal 信息。
例如,定义一个名为`classdesc`的snippet,包括上述的文件头、类说明和函数说明模板。 4. 在XML文件中,使用`<Code>`标签定义代码区域,`<Expansion>`标签定义展开行为,`<Placeholder>`标签定义占位符。 5. 保存XML...
1. **Javadoc的基本结构** Javadoc注释可以包含多行文本,支持HTML标签,使得可以在注释中添加格式化文本、链接和其他元素。例如,你可以使用`<p>`标签创建段落,`<code>`标签高亮代码,`<a>`标签添加超链接等。 2...
3dsMax通过识别继承自`ClassDesc2`类的实例来确定插件接口。此类实现了一系列与类ID、层次信息处理相关的函数,系统据此判断插件的有效性。 #### 2.3 插件调试技巧 调试插件时,需将工程属性设置为Hybrid模式,...
明斯基动态流程系统程序可模拟经济流程(即复杂的系统动态)。 有关完整概述,请参见夹和文件概述的应用程序和DAG引擎概述的描述了Minsky .mky模型文件的架构... Emscripten classdesc描述符可在浏览器中支持Minsky。