Java和Android序列化相关知识点记录

概念

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

反序列化:反之。

常见的序列化协议

  1. Serializable Java的序列化方案
  2. Parcelable Android独有
  3. json,xml,protbuf … 广义的序列化

Serializable

public interface Serializable { 
}

Serializable 用来标识当前类可以被 ObjectOutputStream 序列化,以及被 ObjectInputStream 反序列
化。

public class Student implements Serializable { 
//serialVersionUID唯一标识了一个可序列化的类,假设当前类已经序列化或者持久化到本地,然后修改对象的属性,比如去掉了某个属性,此时再去反序列化成该对象时,会报错,因为SerialVersionUID不一致了。
private static final long serialVersionUID = -2100492893943893602L; 
private String name; 
private String sax; 
private Integer age; 
//Course也需要实现Serializable接口 否则报错
private List<Course> courses; 
//用transient关键字标记的成员变量不参与序列化(在被反序列化后,transient 变量的值被 设为初始值,如 int 型的是 0,对象型的是 null) 
private transient Date createTime; 
//静态成员变量属于类不属于对象,所以不会参与序列化(对象序列化保存的是对象的“状态”,也 就是它的成员变量,因此序列化不会关注静态变量) 
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat();

Externalizable

package java.io;
//读写顺序要求一致、读写的成员变量的个数都一致
public interface Externalizable extends Serializable {
    void writeExternal(ObjectOutput var1) throws IOException;
    void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException;
}

序列化原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单例

在这里插入图片描述

/**
 * 单例类防止反序列化
 */
class Singleton implements Serializable{
    public static Singleton INSTANCE = new Singleton();

    private Singleton(){}


    private Object readResolve(){
        return INSTANCE;
    }
}

/**
 * 单例类如何防止反射
 */
class Singleton1 {

    private static boolean flag = false;

    private Singleton1(){
        synchronized(Singleton.class){
            if(flag == false){
                flag = !flag;
            } else {
                throw new RuntimeException("单例模式被侵犯!");
            }
        }
    }

    private  static class SingletonHolder {
        private static final Singleton1 INSTANCE = new Singleton1();
    }

    public static Singleton1 getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

或者直接用枚举

enum Num1{
    ONE,TWO,THREE;
    public void printValues(){
        System.out.println("ONE: "+ ONE.ordinal() + ", TWO: " + TWO.ordinal() + ", THREE: " + THREE.ordinal());
    }
}

/**
 * Java的序列化机制针对枚举类型是特殊处理的。简单来讲,在序列化枚举类型时,只会存储枚举类的引用和枚举常量的名称。随后的反序列化的过程中,
 * 这些信息被用来在运行时环境中查找存在的枚举类型对象。
 */
public class EnumSerializableTest {
//
    public static void main(String[] args) throws Exception {
        byte[] bs =SerializeableUtils.serialize(Num1.THREE);
        Num1.THREE.printValues();
        System.out.println("hashCode: " + Num1.THREE.hashCode());
        System.out.println("反序列化后");
        Num1 s1 = SerializeableUtils.deserialize(bs);
        s1.printValues();
        System.out.println("hashCode: " + s1.hashCode());
        System.out.println("== " + (Num1.THREE == s1));
    }

}

Q&A

序列化与持久化的关系和区别?
答: 序列化是为了进程间数据交互而设计的, 持久化是为了把数据存储下来而设计的。

序列化与反序列化后的对象是什么关系?
答:是一个深拷贝, 前后对象的引用地址不同,enmu例外。

Android 为什么要设计 bundle 而不是使用 HashMap 结构?
答:bundle 内部适用的是 ArrayMap, ArrayMap 相比 Hashmap 的优点是, 扩容方便, 每次扩容是原容量的一半, 在[百量] 级别, 通过二分法查找 key 和 value (ArrayMap 有两个数组, 一个存放 key 的 hashcode, 一个存放 key+value 的 Entry) 的效率要比 hashmap 快很多, 由于在内存中或者 Android 内部传输中一般数据量较小, 因此用 bundle 更为合适。

Android 中 intent/bundle 的通信原理以及大小限制?
答: Android 中的 bundle 实现了 parcelable 的序列化接口, 目的是为了在进程间进行通讯, 不同的进程共享一片固定大 小的内存, parcelable 利用 parcel 对象的 read/write 方法, 对需要传递的数据进行内存读写, 因此这一块共享内存不能 过大, 在利用 bundle 进行传输时, 会初始化一个 BINDER_VM_SIZE 的大小 = 1 * 1024 * 1024 - 4096 * 2, 即便通过 修改 Framework 的代码, bundle 内核的映射只有 4M, 最大只能扩展到 4M.

为何 Intent 不能直接在组件间传递对象而要通过序列化机制?
答: 因为 Activity 启动过程是需要与 AMS 交互, AMS 与 UI 进程是不同一个的, 因此进程间需要交互数据, 就必须序列化。具体如下:
Intent在启动其他组件时,会离开当前应用程序进程,进入ActivityManagerService进程intent.prepareToLeaveProcess()),这也就意味着,Intent所携带的数据要能够在不同进程间传输。首先我们知道,Android是基于Linux系统,不同进程之间的java对象是无法传输,所以我们此处要对对象进行序列化,从而实现对象在 应用程序进程和ActivityManagerService进程之间传输。
这里插入一张APP启动流程图,以及通信方式
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_ChuTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值