Android Serializable的简单认识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34975710/article/details/53782872

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

生活不只是敲代码,如果你或你身边的人喜欢摄影或者生活的点点滴滴,可以关注下我亲爱的公众号~
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_34975710/article/details/53782872