Serializable

  • 静态变量序列化不会被保存
public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    public static int staticVar = 5;

    public static void main(String[] args) {
try {
//初始时staticVar为5
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Test());
out.close(); //序列化后修改为10
Test.staticVar = 10; ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Test t = (Test) oin.readObject();
oin.close(); //再读取,通过t.staticVar打印新的值
System.out.println(t.staticVar); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

最后的输出是 10

  • 父类的序列化与 Transient 关键字

一个子类实现了 Serializable 接口,它的父类都没有实现 Serializable 接口,序列化该子类对象,然后反序列化后输出父类定义的某变量的数值,该变量数值与序列化时的数值不同。

要想将父类对象也序列化,就需要让父类也实现Serializable 接口。如果父类不实现的话的,就 需要有默认的无参的构造函数。如果你考虑到这种序列化的情况,在父类无参构造函数中对变量进行初始化,否则的话,父类变量值都是默认声明的值,如 int 型的默认是 0,string 型的默认是 null。

我们熟悉使用 Transient 关键字可以使得字段不被序列化,那么还有别的方法吗?根据父类对象序列化的规则,我们可以将不需要被序列化的字段抽取出来放到父类中,子类实现 Serializable 接口,父类不实现,根据父类序列化规则,父类的字段数据将不被序列化。

  • 序列化存储规则
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
Test test = new Test();
//试图将对象两次写入文件
out.writeObject(test);
out.flush();
System.out.println(new File("result.obj").length());
out.writeObject(test);
out.close();
System.out.println(new File("result.obj").length()); ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
//从文件依次读出两个文件
Test t1 = (Test) oin.readObject();
Test t2 = (Test) oin.readObject();
oin.close(); //判断两个引用是否指向同一个对象
System.out.println(t1 == t2);

对同一对象两次写入文件,打印出写入一次对象后的存储大小和写入两次后的存储大小,然后从文件中反序列化出两个对象,比较这两个对象是否为同一对象。一般的思维是,两次写入对象,文件大小会变为两倍的大小,反序列化时,由于从文件读取,生成了两个对象,判断相等时应该是输入 false 才对,但是。。。

我们看到,第二次写入对象时文件只增加了 5 字节,并且两个对象是相等的。。Java 序列化机制为了节省磁盘空间,具有特定的存储规则,当写入文件的为同一对象时,并不会再将对象的内容进行存储,而只是再次存储一份引用,上面增加的 5 字节的存储空间就是新增引用和一些控制信息的空间。反序列化时,恢复引用关系,使得代码中的 t1 和 t2 指向唯一的对象,二者相等,输出 true。该存储规则极大的节省了存储空间。

Parcelable

android.os.BadParcelableException: ClassNotFoundException when unmarshalling

public Config config;
public RowView(Parcel in){
type = in.readString();
interfaceUrl = in.readString();
size = in.readInt();
config = in.readParcelable(null);
}

报错的语句即为config = in.readParcelable(null);

  • 分析

根据android文档介绍:

readParcelable (ClassLoader loader)

loader A ClassLoader from which to instantiate the Parcelable object, or null for the default class loader.即loader为空时系统会采取默认的class loader。

Android有两种不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎么加载android classes,apk classloader知道怎么加载you code,apk classloader继承自framework classloader,所以也知道怎么加载android classes。

在应用刚启动时,默认class loader是apk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,所以对于自己的类会报ClassNotFoundException。

  • 解决

将config = in.readParcelable(null);改为config = in.readParcelable(Config.class.getClassLoader());

Config.class.getClassLoader()即为apk classloader, 其中Config.class可以改为你程序中自己写的任意类,因为他们同样指向apk loader。

试着改为config = in.readParcelable(Activity.class.getClassLoader());你会发现依然ClassNotFoundException因为Activity.class.getClassLoader()指向的是framework classloader

我是天王盖地虎的分割线

参考:http://www.ibm.com/developerworks/cn/java/j-lo-serial/index.html

Android -- Serializable和Parcelable需要注意的的更多相关文章

  1. android Serializable 和 Parcelable 区别

      android 中自定义的对象序列化的问题有两个选择一个是Parcelable,另外一个是Serializable. 一 序列化原因: 1.永久性保存对象,保存对象的字节序列到本地文件中:2.通过 ...

  2. Android序列化之Serializable和Parcelable

    PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...

  3. 浅谈Android中Serializable和Parcelable使用区别

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 Android开发的时候,我们时长遇到传递对象的需求,但是我们无法将对象的引用传给Activity或者Fragment,我们需要将这些对象 ...

  4. Android中Serializable和Parcelable序列化对象详解

    学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.P ...

  5. Android序列化:Parcelable/Serializable

    1.易用性及速度 1.1 Serializable——简单易用 Serializable的作用是为了保存对象的属性到本地文件.数据库.网络流.rmi以方便数据传输,当然这种传输可以是程序内的也可以是两 ...

  6. android序列化(1)Parcelable与Serializable

    1.Android中实现序列化有两个选择 一是实现Serializable接口(是JavaSE本身就支持的),实现Serializable接口非常简单. 一是实现Parcelable接口(是Andro ...

  7. Serializable 和 Parcelable 区别

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html http://www.cnblogs.com/blu ...

  8. android对象序列化Parcelable浅析

    一.android序列化简介 我们已经知道在Android使用Intent/Bindler进行IPC传输数据时,需要将对象进行序列化. JAVA原本已经提供了Serializable接口来实现序列化, ...

  9. 序列化Serializable和Parcelable

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录下序列化Serializable和Parcelable的使用方法. Android中Intent如果要传递类对象,可以通过两 ...

随机推荐

  1. hdu 3853 概率dp

    题意:在一个R*C的迷宫里,一个人在最左上角,出口在右下角,在每个格子上,该人有几率向下,向右或者不动,求到出口的期望 现在对概率dp有了更清楚的认识了 设dp[i][j]表示(i,j)到(R,C)需 ...

  2. 2015 年度新增开源软件排名 TOP 100 - 开源中国社区

    2015 年度新增开源软件排名 TOP 100 - 开源中国社区 39.ABTestingGateway http://www.oschina.net/news/69808/2015-annual-r ...

  3. HDU 4453 Looploop (伸展树splay tree)

    Looploop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. 【shell学习笔记】curl命令总结

    2014-12-16 20:34 文思海辉 =========== CURL命令总结 1. 下载 curl -o [文件名称] www.baidu.com 2. 显示 HTTP request头信息 ...

  5. 《Go学习笔记 . 雨痕》方法

    一.定义 方法 是与对象实例绑定的特殊函数. 方法 是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例都有各自不同的独立特征,以 属性 和 方法 来暴露对外通信接口.普通函 ...

  6. 在线即时展现 Html、JS、CSS 编辑工具 - JSFiddle

    在线即时展现 Html.JS.CSS 编辑工具 - JSFiddle 想对它做些说明介绍.但是它确是那么的easy使用. 兴许有时间,把左側列表作以相关介绍和演示样例演示吧.

  7. VS2015 Offline Help Content is now available in 10 more languages!

    https://blogs.msdn.microsoft.com/devcontentloc/2015/10/21/vs2015-offline-help-content-is-now-availab ...

  8. 哈希小demo hashCode取模

    package demo; import java.util.ArrayList; import java.util.List; class Person { private String usern ...

  9. AngularJS使用OData请求ASP.NET Web API资源的思路

    本篇整理AngularJS使用OData请求ASP.NET Web API资源的思路. 首先给ASP.NET Web API插上OData的翅膀,通过NuGet安装OData. 然后,给control ...

  10. ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现

    在"ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积01, 在控制台实现"中,在控制台应用程序中实现了属性值的笛卡尔乘积.本篇在界面中实现.需要实现的大致如下: 在界面 ...