為了反序列化時不出問題,實現(xiàn)Serializable接口的時候,最好也要設(shè)置下serialVersionUID (serialVersionUID的作用請參照文末說明),但是Android Studio貌似默認(rèn)不能自動添加serialVersionUID。
其實,在Preferences里設(shè)置下就okay了。
-
在
Editor下面找到Inspections, 然后在右側(cè)選擇java
屏幕快照 2018-03-23 上午8.57.56.png -
在
java這一項里找到Serialization issues這一項,并找到它下面的Serializable class without 'serialVersionUID',并把該項勾選即可。 然后點擊apply即可。
Group.png
- 這時候在實現(xiàn)了
Serializable接口的類名上點擊一下,等左邊出現(xiàn)黃色警示燈,然后點擊黃色警示燈,就能看到自動生成serialVersionUID的提示了。
Group 2.png
關(guān)于serialVersionUID的作用解釋:
serialVersionUID是用來輔助序列化和反序列化的。當(dāng)我們把一個對象序列化到本地的時候,serialVersionUID也會一起被寫入序列化的文件中,等下次反序列化的時候,系統(tǒng)會自動比對序列化文件中的serialVersionUID與類中的serialVersionUID是否一致,如果不一致則會拋出異常,發(fā)序列化也會失敗。
如果我們沒有指定serialVersionUID,那么序列化的時候系統(tǒng)會自動根據(jù)當(dāng)前類結(jié)構(gòu)生成一個hash值并寫入序列化文件中。如果下次反序列化的時候我們已經(jīng)對類結(jié)構(gòu)進(jìn)行了修改,那么會導(dǎo)致反序列化時系統(tǒng)自動計算的當(dāng)前類hash值與之前序列化文件中的hash值不一致,從而無法反序列化。
如果我們自己指定了serialVersionUID,那么不管類結(jié)構(gòu)如何改變,序列化到文件中的serialVersionUID是永遠(yuǎn)和我們類中的serialVersionUID一致的,系統(tǒng)會最大限度的幫我們完成反序列化,當(dāng)然,如果類結(jié)構(gòu)發(fā)生了非常規(guī)性的變化,比如修改類名,修改成員變量類型,這時候反序列化也是會失敗的。
序列化和反序列化也是比較簡單的,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();
}
}
}
}
另外,補(bǔ)充一下,靜態(tài)成員變量屬于類,不屬于類對象,所以不會參與序列化。同時,標(biāo)示了transient的成員變量也不在序列化之列。
最后幫朋友打個小廣告


