當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Serializable的簡單認(rèn)識(shí)
Serializable的簡單認(rèn)識(shí)
一、Serializable簡介
Serializable是Java中的一個(gè)提供序列化的接口,可以為對(duì)象提供序列化和反序列化。Serializable接口是一個(gè)空接口,使用起來非常方便,只需要將準(zhǔn)備序列化的類實(shí)現(xiàn)該接口即可。
public interface Serializable {
/* empty */
}
二、Serializable的簡單應(yīng)用
1、對(duì)象的存儲(chǔ)
一般情況下我們見得比較多的是將一些具體的數(shù)據(jù),如數(shù)字、文字、視頻、音頻等會(huì)保存到存儲(chǔ)設(shè)備上,但有的時(shí)候也需要將對(duì)象持久化到存儲(chǔ)設(shè)備上,這個(gè)時(shí)候就需要使用Serializable將對(duì)象持久化的操作,即將對(duì)象保存到存儲(chǔ)設(shè)備上。
通過Serializable的方式非常簡單,因?yàn)榇蠖鄶?shù)工作都由系統(tǒng)完成,我們只需讓對(duì)象的類實(shí)現(xiàn)Serializable接口,并且使用ObjectInputStream和ObjectOutputStream即可完成,來看下面的的列子。
自定義一個(gè)Books類:
public class Books implements Serializable {
private static final long serialVersionUID = 12345678L;
public String name = "紅樓";
public Books(String name) {
super();
this.name = name;
}
}
布局文件就不做介紹,上面就放置兩個(gè)按鈕,一個(gè)實(shí)現(xiàn)序列化,一個(gè)實(shí)現(xiàn)反序列化。對(duì)應(yīng)的MainActivity代碼如下:
public class MainActivity extends Activity {
File file = new File(Environment.getExternalStorageDirectory(),
"serializable.txt");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bt1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
write();
}
});
findViewById(R.id.bt2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
read();
}
});
}
/**
* 實(shí)現(xiàn)序列化存儲(chǔ)
*/
private void write() {
try {
Books books = new Books("三國");
FileOutputStream fout = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(books);
System.out.println("books = " + books);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化從存儲(chǔ)設(shè)備讀取對(duì)象
*/
private void read() {
try {
FileInputStream fin = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fin);
Books books = (Books) in.readObject();
System.out.println("books = " + books);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
上面程序運(yùn)行,點(diǎn)擊序列化按鈕。
在sd卡目錄下找到我們保存的文件,打開。
可以看到我們已經(jīng)將程序中創(chuàng)建的Books對(duì)象book存儲(chǔ)到的sd卡上。點(diǎn)擊反序列化按鈕即可將對(duì)象的數(shù)據(jù)從sd卡反序列化,從新生成一個(gè)Books對(duì)象,如下打印信息所示,可以看到數(shù)據(jù)是一樣的,但是這兩個(gè)對(duì)象并不是同一個(gè)了。
大家會(huì)發(fā)現(xiàn)在Books類中聲明了一個(gè)serialVersionUID,這個(gè)常量并不是必須的,不聲明也可實(shí)現(xiàn)對(duì)象的序列化,但是在一些情況下會(huì)對(duì)反序列化產(chǎn)生影響。如果我們不去自己指定一個(gè)serialVersionUID,在序列化時(shí)會(huì)按照類的結(jié)構(gòu)自動(dòng)生成一個(gè)serialVersionUID值,但是在序列化存儲(chǔ)后改變了類的結(jié)構(gòu),如增加和刪除成員變量,重新編譯運(yùn)行后直接進(jìn)行反序列化的話,這個(gè)時(shí)候會(huì)出現(xiàn)反序列化失敗。
在序列化時(shí)會(huì)將serialVersionUID值也寫入序列化的文件中,當(dāng)我們把類的結(jié)構(gòu)改變后,當(dāng)前類中的serialVersionUID會(huì)重新生成,這就導(dǎo)致文件中serialVersionUID和目前的serialVersionUID不一致,就如上面輸出信息提示所示,這將會(huì)導(dǎo)致反序列化失敗。
但是當(dāng)手動(dòng)指定serialVersionUID后,如果將類的結(jié)構(gòu)改變之后,反序列化依舊會(huì)成功,并且將大程度的恢復(fù)數(shù)據(jù)。還是上面那個(gè)例子,先進(jìn)行序列化,然后在Books類中增加一個(gè)成員變量:
public class Books implements Serializable {
private static final long serialVersionUID = 12345678L;
public String name = "紅樓";
public int price = 100;
public Books(String name) {
super();
this.name = name;
}
}
/**
* 反序列化從存儲(chǔ)設(shè)備讀取對(duì)象
*/
private void read() {
try {
FileInputStream fin = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fin);
Books books = (Books) in.readObject();
// 打印輸出類中的成員變量
System.out.println("books = " + books+" "+books.name+" "+books.price);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
然后重新編譯運(yùn)行直接反序列化:
可以看到這次反序列化成功,并且原本序列化文件中并沒有“price”的數(shù)據(jù),通過自己指定serialVersionUID后能避免類似的情況,這里就給該屬性附了一個(gè)默認(rèn)值0。
2、對(duì)象的傳遞
這里只是介紹利用Intent傳遞對(duì)象,Intent默認(rèn)沒有提供一個(gè)方法直接去傳遞一個(gè)對(duì)象,但是可以將對(duì)象序列化后便可。Intent中的putExtra方法就可以傳遞一個(gè)Serializable 類型的數(shù)據(jù),所以只需要這個(gè)類實(shí)現(xiàn)Serializable 接口即可。
putExtra(String name, Serializable value)
如下所示:
Books books = new Books("三國");
Intent intent = new Intent();
intent.putExtra("data", books);
在接收數(shù)據(jù)時(shí)利用intent中對(duì)應(yīng)的Serializable getSerializableExtra(String name)方法即可。
Books newbook = (Books) intent.getSerializableExtra("data");