相关知识点:RMI

关键点:

Serializable


1.一个类只要继承Serializable,就可以被序列化

2.静态变量不会保存,序列化只针对变量,不针对方法

3.通过ObjectOutputStream进行序列化,ObjectInputStream反序列化

4.虚拟机是否允许反序列化,不仅跟存储路径、功能代码是否一致,另一个非常重要的因素的序列化ID是否一致(private static final Long serialiVersionUID)

5.通过在变量前面加入关键字transient,可以阻止该变量序列化到文件中,当反序列化时,该变量被设置为初始值,int->0 string->null

6.服务器给客户端发送序列化数据时,如果里面有敏感数据(例如密码),可以在序列化时加密,而客户端拥有解密的密钥,这样就可以保证通信安全。

7.ArrayList实现了Serializable,AttayList底层存储数据的是一个数组,这个数组变量被transient修饰符修饰,但是我们存进去数据后,对ArrayList对象进行序列化却可以将数据保存下去,这是因为ArrayList 定义了writeObject()和readObject(),被序列化的类定义了这两个方法,虚拟机就会调用者两个方法来实现自定义序列化和反序列化。相反,如果,没有定义,默认会调用ObjectOutputStream的defaultWriteObject()方法,ObjectInputStream的defaultReadObject()。ArrayList之所以要讲内部数组定义为transient,再重写序列化方法,是因为数组很大的话,假如数组长度为100,但是只有一个值,其它为null,如果此时直接把数组序列化,就会做大量的无用功,所以将内部数组定义为transient,同时为了满足内部数据可以被序列化,就重写了writeObject()和readObject()

8.要实现自定义序列化,只需要在序列化类中,添加writeObject()和readObject()

9.通过反射调用writeObject()和readObject()

10.Serializable只是一个空接口,当序列化的时候对类型检查来保证只有实现Serializable的类或者属于Enum/Array类的一种才能被序列化

11.Serializable没有属性和方法,只是用来标记是否可以序列化

12.可序列化的所有子类,都可以序列化

13.还有一个接口:Externalizable继承Serializable,并且它会强制继承者自己实现writeObject()和readObject(),不然数据就不会被序列化,只有类结构被序列化,当反序列化时,对象参数都是默认值。

14.序列化ID两种生成策略:1.固定值1L,2,使用jdk工具生成一个随机的long类型数据,不同的编译器可能生成的值不同,所以序列化ID最好固定死后(1L)不要动,否则容易导致无法解析旧数据对象。

15.如果一个类的所有父类都没有被序列化,此时想要序列化,则它的所有父类都 必须要有一个空参的构方法,因为父类不能序列化,但是所有的子类都是从父类来的,反序列化的时候就需要通过这个 构造函数构造出一个父类,父类的所有值都是默认值。

16.将一个对象序列化两次,占用的内存只会比一个对象序列化占用的内存多一点点,因为java序列化机制对同一个对象多次序列化做了优化以节省存储空间,第二个只会拥有第一个的引用,当反序列化后,这两个对象是想等的。注意,当第一次序列化后,修改对象后再序列化,第二个序列化还是只会拥有第一个序列化的引用,所以此次修改对序列化后的数据无效,取出两个对象值相同,因为还是优化机制,只会判断是否是一个对象,并不会判断对象值是否相等。

Parcelable

  1. Intent之间可以传递简单的数据,但是当数据结构比较复杂时就需要进行序列化
  2. Parcelable作为中间层,底层利用c++直接操作内存

两者对比:


1.Parcelable内存使用优于Serializable

2.Serializable在序列化时会产生大量的临时变量(反射机制),会导致大量的GC,所以性能上会略逊色。

3.Parcelable是以IBindler作为载体的,内存开销小,所以当消息传递对象时(内存之间传递),一般使用Parcelable。

4.Parcelable直接在内存中进行读写,而Serializable是以字节流的形式写入到硬盘的。

5.Parcelable并不能持久的存储数据,它只是在传递时比较有优势,对于那些需要长久保存的对象,还是需要Serializable。

1.什么是?

序列化就是一种持久保存对象的手段,而反序列化就是对持久保存的对象进行读取。

现已广泛应用于:持久化对象、RMI(远程方法调用)、远程传递对象


Parcelable是Android SDK提供的用来序列化和反序列化的一种方式。

2.为什么要?

我们知道,java平台运行我们创建可复用的对象,但通常这些对象只有当JVM运行期间才有效,也就是普通的对象的生命周期肯定小于JVM的生命周期。在实际开发过程了,我们可能需要保留一些对象,保留期限超过JVM生命周期,这个时候需要一种技术,来满足这种要求。

序列化就出现了,他通过将对象状态存储为一组字节,当需要的时候,进行从字节到对象的转化(反序列化)。由于只是存储对象的状态,所以它不会存储静态变量。


Java提供的Serializable,进行序列化或者反序列化都 需要大量的I/O操作,成本太大,不适合Android面向的小内存设备,所以需要一种开销小的方式来进行序列化和反序列化,它就是Parcelable

54

3.怎么使用?

文本描述:如果一个类想要实现序列化,只需要继承Serializable

实际操作演示:

User类

import java.beans.Transient;
import java.io.Serializable;

public class User implements Serializable {
    private static String age="18";
    private String name;
     private transient String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

实际操作类:

import java.io.*;

public class Main {
    private static String FILE_NAME="temp";
    public static void main(String[] args) throws Exception {
        User user=new User();
        user.setName("小马哥");
        user.setSex("小帅锅");
        System.out.println(user);

        //将对象写入文件
        ObjectOutputStream objectOutputStream=
                new ObjectOutputStream(new FileOutputStream(FILE_NAME));
        objectOutputStream.writeObject(user);
        //注意,正确做法应该使用try----finally来关闭
        objectOutputStream.close();

        //为了看出static没有被实例化,修改age的值
        User.age="20";

        //将对象从文件红读取到内存中
        File file=new File(FILE_NAME);
        ObjectInputStream  objectInputStream=new ObjectInputStream(new FileInputStream(file));
        User oldUser= (User) objectInputStream.readObject();
        System.out.println("从文件读取的对象"+oldUser);

    }
}

最后结果:

User{name='小马哥', sex='小帅锅', age='18'}
从文件读取的对象User{name='小马哥', sex='null', age='20'}

Parcalable:

User:

package com.xiaomage.parcelabledemo;

import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {

    public User(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    protected User(Parcel in) {
        //从序列化中创建对象:反序列化操作
        name = in.readString();
        sex=in.readString();
        age=in.readString();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            //从序列化中创建对象:反序列化操作
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            //创建指定长度的原始对象数组
            return new User[size];
        }
    };

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        //将对象写入序列化中
        dest.writeString(name);
        dest.writeString(age);
        dest.writeString(sex);
    }
    @Override
    public int describeContents() {
        //几乎所有的情况都返回0,仅在当前对象存在文件描述符时返回1
        return 0;
    }



    public static String age="18";
    private String name;
    private transient String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

4.实现原理

results matching ""

    No results matching ""