- 为什么需要序列化?
- 序列化使用场景?
序列化常见出错问题?
不实现序列化接口进行保存对象会出现如下错误,可以通过实现Serializable接口解决问题。
Exception in thread "main" java.io.NotSerializableException: home.s.Rule
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at home.s.Serial.main(Serial.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
修改序列号id则会出现如下问题:
Exception in thread "main" java.io.InvalidClassException: home.s.Rule; local class incompatible: stream classdesc serialVersionUID = 1234000, local class serialVersionUID = 123400
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at home.s.DESerial.main(DESerial.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
出现这个问题是因为序列号被认为改动导致。这时可能大多数同学会说,可不可以不使用序列号,而使用Java本身默认的。
如下是Java默认生成序列号源码,大概意思请自行阅读。
/**
* Return the serialVersionUID for this class. The serialVersionUID
* defines a set of classes all with the same name that have evolved from a
* common root class and agree to be serialized and deserialized using a
* common format. NonSerializable classes have a serialVersionUID of 0L.
*
* @return the SUID of the class described by this descriptor
*/
public long getSerialVersionUID() {
// REMIND: synchronize instead of relying on volatile?
if (suid == null) {
suid = AccessController.doPrivileged(
new PrivilegedAction<Long>() {
public Long run() {
return computeDefaultSUID(cl);
}
}
);
}
return suid.longValue();
}
但是这里还是强烈建议使用一个序列化版本号,因为默认的版本号非常敏感,并且依赖于编译器,如果实体类在序列化之前和之后数据结构有所改变,则会导致如下问题:
Exception in thread "main" java.io.InvalidClassException: home.s.Rule; local class incompatible: stream classdesc serialVersionUID = -1031401772392262459, local class serialVersionUID = 7635324993874063726
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at home.s.DESerial.main(DESerial.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
具体测试源码如下:
实体类:
package home.s;
import java.io.Serializable;
public class Rule implements Serializable{
private static final long serialVersionUID = 1234000L;
public Rule(Long id, String type) {
this.id = id;
this.type = type;
}
private Long id;
private String type;
// private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
/* public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}*/
}
序列化
Rule rule = new Rule(1232L, "asdf");
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:\\222.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
oos.writeObject(rule);
oos.flush();
fileOutputStream.close();
反序列化
FileInputStream fis = new FileInputStream(new File("D:\\222.txt"));
ObjectInputStream ois = new ObjectInputStream(fis);
Rule o = (Rule) ois.readObject();
System.out.println(Json.toJson(o));