参考网址:Serializable的简单认识
一、Serializable简介
Serializable是Java中的一个提供序列化的接口,可以为对象提供序列化和反序列化。Serializable接口是一个空接口,使用起来非常方便,只需要将准备序列化的类实现该接口即可。
public interface Serializable {
/* empty */
}
二、Serializable的简单应用
1、对象的存储
一般情况下我们见得比较多的是将一些具体的数据,如数字、文字、视频、音频等会保存到存储设备上,但有的时候也需要将对象持久化到存储设备上,这个时候就需要使用Serializable将对象持久化的操作,即将对象保存到存储设备上。
通过Serializable的方式非常简单,因为大多数工作都由系统完成,我们只需让对象的类实现Serializable接口,并且使用ObjectInputStream和ObjectOutputStream即可完成,来看下面的的列子。
自定义一个Books类:
public class Books implements Serializable {
private static final long serialVersionUID = 12345678L;
public String name = "紅楼";
public Books(String name) {
super();
this.name = name;
}
}
布局文件就不做介绍,上面就放置两个按钮,一个实现序列化,一个实现反序列化。对应的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();
}
});
}
/**
* 实现序列化存储
*/
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();
}
}
/**
* 反序列化从存储设备读取对象
*/
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();
}
}
}
上面程序运行,点击序列化按钮
这里写图片描述
在sd卡目录下找到我们保存的文件,打开
这里写图片描述 这里写图片描述
可以看到我们已经将程序中创建的Books对象book存储到的sd卡上。点击反序列化按钮即可将对象的数据从sd卡反序列化,从新生成一个Books对象,如下打印信息所示:
这里写图片描述
可以看到数据是一样的,但是这两个对象并不是同一个了。
大家会发现在Books类中声明了一个serialVersionUID,这个常量并不是必须的,不声明也可实现对象的序列化,但是在一些情况下会对反序列化产生影响。如果我们不去自己指定一个serialVersionUID,在序列化时会按照类的结构自动生成一个serialVersionUID值,但是在序列化存储后改变了类的结构,如增加和删除成员变量,重新编译运行后直接进行反序列化的话,这个时候会出现反序列化失败。
这里写图片描述
在序列化时会将serialVersionUID值也写入序列化的文件中,当我们把类的结构改变后,当前类中的serialVersionUID会重新生成,这就导致文件中serialVersionUID和目前的serialVersionUID不一致,就如上面输出信息提示所示,这将会导致反序列化失败。
但是当手动指定serialVersionUID后,如果将类的结构改变之后,反序列化依旧会成功,并且将最大程度的恢复数据。还是上面那个例子,先进行序列化,然后在Books类中增加一个成员变量:
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;
}
}
/**
* 反序列化从存储设备读取对象
*/
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();
}
}
然后重新编译运行直接反序列化:
这里写图片描述
可以看到这次反序列化成功,并且原本序列化文件中并没有“price”的数据,通过自己指定serialVersionUID后能避免类似的情况,这里就给该属性附了一个默认值0。
2、对象的传递
这里只是介绍利用Intent传递对象,Intent默认没有提供一个方法直接去传递一个对象,但是可以将对象序列化后便可。Intent中的putExtra方法就可以传递一个Serializable 类型的数据,所以只需要这个类实现Serializable 接口即可。
putExtra(String name, Serializable value)
如下所示:
Books books = new Books("三国");
Intent intent = new Intent();
intent.putExtra("data", books);
在接收数据时利用intent中对应的Serializable getSerializableExtra(String name)方法即可。
Books newbook = (Books) intent.getSerializableExtra("data");
网友评论