Serializable的简单认识

作者:华清远见讲师

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");

展开阅读全文

没有更多推荐了,返回首页