为了反序列化时不出问题,实现Serializable
接口的时候,最好也要设置下serialVersionUID
(serialVersionUID
的作用请参照文末说明),但是Android Studio
貌似默认不能自动添加serialVersionUID
。
其实,在Preferences
里设置下就okay了。
-
在
Editor
下面找到Inspections
, 然后在右侧选择java
-
在
java
这一项里找到Serialization issues
这一项,并找到它下面的Serializable class without 'serialVersionUID'
,并把该项勾选即可。 然后点击apply
即可。
- 这时候在实现了
Serializable
接口的类名上点击一下,等左边出现黄色警示灯,然后点击黄色警示灯,就能看到自动生成serialVersionUID
的提示了。
关于serialVersionUID
的作用解释:
serialVersionUID
是用来辅助序列化和反序列化的。当我们把一个对象序列化到本地的时候,serialVersionUID
也会一起被写入序列化的文件中,等下次反序列化的时候,系统会自动比对序列化文件中的serialVersionUID
与类中的serialVersionUID
是否一致,如果不一致则会抛出异常,发序列化也会失败。
如果我们没有指定serialVersionUID
,那么序列化的时候系统会自动根据当前类结构生成一个hash
值并写入序列化文件中。如果下次反序列化的时候我们已经对类结构进行了修改,那么会导致反序列化时系统自动计算的当前类hash
值与之前序列化文件中的hash值不一致,从而无法反序列化。
如果我们自己指定了serialVersionUID
,那么不管类结构如何改变,序列化到文件中的serialVersionUID
是永远和我们类中的serialVersionUID
一致的,系统会最大限度的帮我们完成反序列化,当然,如果类结构发生了非常规性的变化,比如修改类名,修改成员变量类型,这时候反序列化也是会失败的。
序列化和反序列化也是比较简单的,demo如下:
public class User implements Serializable {
private static final long serialVersionUID = -4211449776975163975L;
private int userId;
private String userName;
// ....
}
/*- 序列化和反序列化 -*/
private void serialAndUnSerial() {
String path = getExternalCacheDir() + "/cache.txt";
// 序列化到本地
User user = new User();
user.setUserId(0);
user.setUserName("Bob");
ObjectOutputStream outputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(path);
outputStream = new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 反序列化
User user1 = null;
ObjectInputStream inputStream = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(path);
inputStream = new ObjectInputStream(fileInputStream);
user1 = (User) inputStream.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
另外,补充一下,静态成员变量属于类,不属于类对象,所以不会参与序列化。同时,标示了transient的成员变量也不在序列化之列。
最后帮朋友打个小广告