1 序列化的原因
java序列化主要是為了跨平臺蹂窖,實現(xiàn)對象的一致性退盯,可在不同的平臺上,保持自己原有的屬性和方法不變
2 序列化的作用
- 永久的保存對象數(shù)據(jù)(將對象數(shù)據(jù)保存在文件當(dāng)中身堡,活著是磁盤中)们童;
- 在網(wǎng)絡(luò)上傳送對象的字節(jié)序列
- 通過RMI傳輸對象(不懂,囧)
- 將對象數(shù)據(jù)在進(jìn)程之間進(jìn)行傳遞
3 序列化的實現(xiàn)方式
3.1 實現(xiàn)Serializable接口
public class Person implements Serializable {
/**
* 序列化id
*/
private static final long serialVersionUID = 112347861234817234L;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
測試demo:
public class SerializableDemo {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Person person = new Person();
person.setName("周杰倫");
person.setAge(36);
person.setSex("男");
serializablePerson(person);
Person newPerson = deSerializablePerson();
System.err.println(MessageFormat.format("name={0},age={1},sex={2}", newPerson.getName(), newPerson.getAge(),
newPerson.getSex()));
}
/**
* 序列化對象
*
* @param person
* @throws FileNotFoundException
* @throws IOException
*/
private static void serializablePerson(Person person) throws FileNotFoundException, IOException {
File file = new File("./person.txt");
if (!file.exists()) {
file.createNewFile();
}
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(person);
System.out.println("Person對象序列化成功!");
oos.close();
}
/**
* 反序列化得到對象
*
* @return
* @throws FileNotFoundException
* @throws IOException
* @throws ClassNotFoundException
*/
private static Person deSerializablePerson() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("./person.txt")));
Person person = (Person) ois.readObject();
System.out.println("Person對象反序列化成功!");
return person;
}
}
首先查看序列化后的文件內(nèi)容:
運行結(jié)果:
序列化成功后敦跌,會在當(dāng)前類文件目錄下生成一個person.txt文件
注釋掉序列化代碼后:
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// Person person = new Person();
// person.setName("周杰倫");
// person.setAge(36);
// person.setSex("男");
// serializablePerson(person);
Person newPerson = deSerializablePerson();
System.err.println(MessageFormat.format("name={0},age={1},sex={2}", newPerson.getName(), newPerson.getAge(),
newPerson.getSex()));
}
通過文件澄干,反序列化逛揩,結(jié)果是:
我們可以看見Person類里面有個serialVersionUID,這個serialVersionUID是用來干什么的?
首先我們修改一下serialVersionUID麸俘,運行一下demo辩稽,看看結(jié)果:
Exception in thread "main" java.io.InvalidClassException: com.haizhi.Person; local class incompatible: stream classdesc serialVersionUID = 112347861234817234, local class serialVersionUID = 112347861234817235
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:617)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at com.haizhi.SerializableDemo.deSerializablePerson(SerializableDemo.java:55)
at com.haizhi.SerializableDemo.main(SerializableDemo.java:21)
報了一個異常,說明反序列化失敶用摹逞泄;
Java序列化機(jī)制會根據(jù)serialVersionUID作序列化版本比較,反序列化時拜效,如果發(fā)現(xiàn)序列化數(shù)據(jù)里面的serialVersionUID與model類的serialVersionUID不同喷众,就會導(dǎo)致反序列化失敗,出現(xiàn)序列化版本不一致的異常紧憾;
當(dāng)實現(xiàn)Serializable接口的實體類沒有顯示定義serialVersionUID到千,serialVersionUID對類的詳細(xì)信息具有較高的敏感性,一個空格的修改就會導(dǎo)致serialVersionUID的變化赴穗,Java序列化機(jī)制會根據(jù)編譯器實現(xiàn)的不同可能千差萬別憔四,這樣在反序列化過程可能會導(dǎo)致意外的 InvalidClassException;
為了保證serialVersionUID在不同java編譯器實現(xiàn)的一致性般眉,為了實現(xiàn)序列化接口的實體能夠兼容先前版本了赵,強(qiáng)烈建議顯示聲明serialVersionUID;
顯式地定義serialVersionUID有兩種用途:
- 在某些場合甸赃,希望類的不同版本對序列化兼容斟览,因此需要確保類的不同版本具有相同的serialVersionUID;
- 在某些場合辑奈,不希望類的不同版本對序列化兼容苛茂,因此需要確保類的不同版本具有不同的serialVersionUID。
3.2 實現(xiàn)Parcelable接口
Parcelabel 的實現(xiàn)鸠窗,需要在類中添加一個靜態(tài)成員變量 CREATOR妓羊,這個變量需要繼承 Parcelable.Creator 接口。
public class Student implements Parcelable{
private int name;
private String grade;
private int score;
public Students(Parcel source){
name = sourece.readString();
grade = source.readString();
score = source.readInt();
}
public int getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public int getScore(){
return score;
}
public void setScore(int score){
this.score = score;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(name);
dest.writeString(grade);
dest.writeInt(score);
}
//Interface that must be implemented and provided as a public CREATOR field that generates instances of your Parcelable class from a Parcel.
public final static Parcelable.Creator<Students> CREATOR = new Parcelable.Creator<Students>() {
@Override
public Students createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new Students(source);
}
@Override
public Students[] newArray(int size) {
// TODO Auto-generated method stub
return new Students[size];
}
};
}
3.3 把對象包裝成JSON字符串傳輸
4 序列化比較
1稍计、在使用內(nèi)存的時候Parcelable比Serializable的性能高躁绸;
2、Serializable在序列化的時候會產(chǎn)生大量的臨時變量臣嚣,從而引起頻繁的GC(內(nèi)存回收)净刮;
3、Parcelable不能使用在將對象存儲在磁盤上這種情況硅则,因為在外界的變化下Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性淹父;