美文网首页
Android Serializable的简单认识

Android Serializable的简单认识

作者: KingWorld | 来源:发表于2020-09-25 10:02 被阅读0次

    参考网址: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");
    

    相关文章

      网友评论

          本文标题:Android Serializable的简单认识

          本文链接:https://www.haomeiwen.com/subject/aagxuktx.html