android序列化

百度百科

1.概念

(1)序列化

概念:将数据结构或对象转换成二进制串的过程。

(2)反序列化

概念:将在序列化生成的二进制串转换成数据结构或对象的过程。

(3)持久化

概念:把数据结构或对象存储起来(文件,硬盘等)。

2.实现

代码

public class Demo {
​
    public static void main(String[] args) throws Exception {
        //Serializable
        String fileName = "/Users/macbook/Desktop/aa/user.txt";
        User user = new User();
        user.setName("哈哈");
        user.setAge(100);
        writeObject(user, fileName);
        User userBack = (User) readObject(fileName);
        System.out.println("read serializable user:name=" + userBack.getName() + ";age:" + userBack.getAge());
        //read serializable user:name=哈哈;age:0
​
        //Externalizable
        String fileName2 = "/Users/macbook/Desktop/aa/user2.txt";
        User2 user2 = new User2();
        user2.setName("哈哈2");
        user2.setAge(200);
        writeObject(user2, fileName2);
        User2 userBack2 = (User2) readObject(fileName2);
        System.out.println("read serializable user:name=" + userBack2.getName() + ";age:" + userBack2.getAge());
        //read serializable user:name=哈哈2;age:200
    }
​
    // 把对象序列化到文件
    private static void writeObject(Object object, String fileName) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName));
        oos.writeObject(object);
        oos.close();
    }
​
    // 反序列化到内存
    private static Object readObject(String fileName) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
        Object object = ois.readObject();
        ois.close();
        return object;
    }
}

2.1 Serializable

public class User implements Serializable {
​
    //不反序列化的话,一般不需要写serialVersionUID
    private static final long serialVersionUID = -1188549698363555384L;
​
    private String name;
​
    private transient int age;
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
}

serialVersionUID

Android自动生成serialVersionUID方法链接

作用:用于检测序列化操作与反序列化操作是否一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

报错如下:

Exception in thread "main" java.io.InvalidClassException: com.example.demo.study.xlh.User; local class incompatible: stream classdesc serialVersionUID = -1188549698363555384, local class serialVersionUID = -1188549698363555386

transient

作用:修饰不会被序列化的属性

注意事项:

  • 静态变量不能被序列化。

  • Serializable序列化后增加或者减少字段,当不指定serialVersionUID时反序列化失败。

  • 一个对象要进行序列化,如果该对象成员变量是引用类型的,那这个引用类型也一定要是可序列化的,否则报错:NotSerializableException。

  • 如果类是可序列化的,但是其父类是不可序列化的,反序列化后不能拿到父类的属性值。

  • 父类实现了Serializable接口,子类继承了父类,没有实现Serializable接口,那么子类同样也是可被序列化的。

介绍文章

2.2Externalizable

public class User2 implements Externalizable {
​
    public User2() {
    }
​
    public User2(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    private String name;
​
    private transient int age;
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeObject(age);
    }
​
    @Override
    public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
        name = (String) in.readObject();
        age = (int) in.readObject();
    }
}

Externalizable接口扩展自java.io.Serializable接口。实现java.io.Serializable即可获得对类的对象的序列化功能。而Externalizable可以通过writeExternal()和readExternal()方法可以指定序列化哪些属性。

注意事项:

  • Externalizable会调用默认的构造器,没有默认构造器则报错:Exception in thread "main" java.io.InvalidClassException: com.example.demo.study.xlh.User2; no valid constructor。Serializable不会调用默认构造器。

  • 继承Externalizable接口时,transient无效,属性是否要序列化,主要通过writeExternal()和readExternal()方法。

  • Externalizable的writeExternal写入顺序要和readExternal读取顺序一致,否则报错:

 @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeObject(age);
    }
​
    @Override
    public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
        age = (int) in.readObject();
        name = (String) in.readObject();
    }
//Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

2.3Parcelable

public class User3 implements Parcelable {
​
    private String name;
​
    private int age;
​
    private transient int sex;
​
    protected User3(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
​
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
​
    @Override
    public int describeContents() {
        return 0;
    }
​
    public static final Creator<User3> CREATOR = new Creator<User3>() {
        @Override
        public User3 createFromParcel(Parcel in) {
            return new User3(in);
        }
​
        @Override
        public User3[] newArray(int size) {
            return new User3[size];
        }
    };
}

androidstudio快速生成Parcelable文章

Parcelable介绍文章

Parcel提供了一套机制,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象。

3.对比

Serializableparcelable
通过io对硬盘操作,速度较慢直接内存操作,效率高,性能好
大小不受限制一般不超过1M,修改内核也只能4M
大量使用反射,产生内存碎片
存储设备或者网络传输应用程序在内存间数据传输

参考资料:Android序列化总结 - 简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值