序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。

在Java中创建的对象,只要没有被回收就可以被复用,但是,创建的这些对象都是存在于JVM的堆内存中,JVM处于运行状态时候,这些对象可以复用,

但是一旦JVM停止,这些对象的状态也就丢失了。

在实际生活中,需要将对象持久化,需要的时候再重新读取出来,通过对象序列化,可以将对象的状态保存为字节数组,需要的时候再将字节数组反序列化为对象。

对象序列化可以很容易的在JVM中的活动对象和字节数组(流)之间转换,广泛用于RMI(远程方法调用)以及网络传输中。

特别注意:

a.静态成员变量属于类不属于对象,所以不会参与序列化(对象序列化保存的是对象的“状态”,也就是它的成员变量,因此序列化不会关注静态变量)

b.用transient关键字标记的成员变量不参与序列化(在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null)

(1).Serializable

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
 import java.io.Serializable;

 public class StudentSerializable implements Serializable {

     //指定serialVersionUID,
//因为原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同时才能被正常的反序列化
//最好自己指定UID或者系统生成,因为如果增加或者删除了某些成员变量,那么系统就会重新生成hash值然后赋给UID,导致反序列化时候crash
private static final long serialVersionUID = 10000000000000000L; private int Uid;
private String Name ; public int getUid() {
return Uid;
}
public void setUid(int uid) {
Uid = uid;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
@Override
public String toString() {
return "StudentSerializable [Uid=" + Uid + ", Name=" + Name + "]";
} }
 private void DealSerializable() throws IOException {
// Initializes The Object
StudentSerializable stu = new StudentSerializable();
stu.setUid(9027);
stu.setName("fish"); File extDir = Environment.getExternalStorageDirectory();
String filename = "tempFile.txt";
File fullFilename = new File(extDir, filename); try {
fullFilename.createNewFile();
fullFilename.setWritable(Boolean.TRUE);
fullFilename.setReadable(Boolean.TRUE); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Write Obj to File
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(fullFilename.getAbsoluteFile()));
oos.writeObject(stu);
} catch (IOException e) {
e.printStackTrace();
} finally {
//oos.close();
} // Read Obj from File
//File file = new File("tempFile.txt");
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(fullFilename.getAbsoluteFile()));
StudentSerializable newStu = (StudentSerializable) ois.readObject();
System.out.println(newStu);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
//ois.close();
}
}

在使用时,通常是和ObjectOutputStream 以及 ObjectInputStream 配套一起使用,准确的说是和ObjectOutputStream 里的writeObject () 和 ObjectInputStream 里的 readObject () 一起使用。writeObject()方法是最重要的方法,用于对象序列化。如果对象包含其他对象的引用,则writeObject()方法递归序列化这些对象。

(2).Parcelable

 import android.os.Parcel;
import android.os.Parcelable; public class StudentParcelable implements Parcelable{ private int Uid;
private String Name ; private Book book ; public StudentParcelable(int uid, String name) {
super();
Uid = uid;
Name = name;
} public int getUid() {
return Uid;
}
public void setUid(int uid) {
Uid = uid;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
} //功能:返回当前对象的内容描述,如果含有文件描述符,返回1
//即CONTENTS_FILE_DESCRIPTOR
//几乎所有情况都会返回0
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
} /**
* 序列化功能由writeToParcel完成,最终通过Parcel的一系列Write方法完成
*/
//功能:将当前对象写入序列化结构中,其中flags标识有两种值,0或1
//为1时标识当前对象需要作为返回值返回,不能立刻释放资源,即PARCELABLE_WRITE_RETURN_VALUE
//不过几乎所有情况都为0
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeInt(Uid);
dest.writeString(Name);
dest.writeParcelable(book, 0);
} /**
* 反序列化由CREATOR来完成,其内部标明了如何创建序列化对象和数组
* 并通过Parcel的一系列read方法来完成反序列化
*/
public StudentParcelable(Parcel source){
Uid = source.readInt();
Name = source.readString(); //注意:book是一个可序列化对象,所以它的反序列化过程需要传递当前线程的上下文类加载器
//否则会报找不到类的错误
book = source.readParcelable(Thread.currentThread().getContextClassLoader());
} public static final Parcelable.Creator<StudentParcelable> CREATOR = new Parcelable.Creator<StudentParcelable>() { //功能: 从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。
@Override
public StudentParcelable createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new StudentParcelable(source);
} //功能:创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。方法是供外部类反序列化本类数组使用。
@Override
public StudentParcelable[] newArray(int size) {
// TODO Auto-generated method stub
return new StudentParcelable[size];
}
}; }
 Intent intent = new Intent(this,Second.class);
StudentParcelable stu = new StudentParcelable(001,"fish");
intent.putExtra("student", stu);
startActivity(intent);
 Intent intent = getIntent();
StudentParcelable stu = (StudentParcelable) intent.getParcelableExtra("student");
Log.i("LOG", "student name :" + stu.getName());
Log.i("LOG", "student age :" + stu.getUid());

两者区别:

1.Serializable实现简单,而Parcelable需要实现特殊的接口

2.Serializable将对象转化为字节流存储在外部设备,需要时重新生成对象(依靠反射),因为使用反射,所以会产生大量的临时变量,从而引起频繁的GC,相比之下Parcelable性能更高,Parcelable的效率是Serializable的十倍以上,所以在内存中传输时更推荐Parcelable(比如在网络中传输对象或者进程间传输对象,还有Intent)

3.Parcelable的整个过程都在内存中进行,反序列化读取的就是原对象,不会创建新对象。要注意的是:不能使用要将数据存储在磁盘上(比如永久性保存对象,或者保存对象的字节序列到本地文件中),因为Parcel是为了更好的实现在IPC间传递对象,并不是一个通用的序列化机制,当改变任何Parcel中数据的底层实现都可能导致之前的数据不可读取(Parcelable 是以2进制的方式写入,严重依赖写入顺序),还有就是Parcelable为了效率完全没有考虑版本间的兼容性,所以数据持久化还是要使用Serializable(比如外部设备保存对象状态或者网络传输对象)

快速解析和序列化Json对象的类库:LoganSquare

注意:

1.如果一个类想被序列化,需要实现Serializable接口。否则将抛出NotSerializableException异常,这是因为,在序列化操作过程中会对类型进行检查,要求被序列化的类必须属于Enum、Array和Serializable类型其中的任何一种,这也是为什么Serializable虽然是一个空接口,但是只要实现了该接口就能序列化和反序列化。

2.在类中增加writeObject 和 readObject 方法可以实现自定义序列化策略,虽然这俩方法不是被显示调用,但是因为在使用ObjectOutputStream的writeObject方法和ObjectInputStream的readObject方法时,会通过反射的方式调用到它们。

参考:http://www.hollischuang.com/archives/1140#What%20Serializable%20Did

序列化与反序列化总结(Serializable和Parcelable)的更多相关文章

  1. 序列化、反序列化(Serializable特性)

    //需要被实例化的类 using System.Collections; using UnityEngine; [Serializable] public class SerializableClas ...

  2. Android序列化之Serializable和Parcelable

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

  3. 序列化Serializable和Parcelable

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

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

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

  5. 【Android - IPC】之Serializable和Parcelable序列化

    1.序列化的目的 (1)永久的保存对象数据(将对象数据保存到文件或磁盘中): (2)通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的,因此序列化的目的是将对象数据 ...

  6. Java序列化与反序列化(Serializable)

    Java序列化与反序列化(Serializable) 特别注意: 1.要序列化的类必须实现Serializable借口 2.在反序列化(读取对象)的时候必须额外捕获EOFException 3.序列化 ...

  7. 使用Serializable接口进行JAVA的序列化和反序列化

    OBJECT STREAMS – SERIALIZATION AND DESERIALIZATION IN JAVA EXAMPLE USING SERIALIZABLE INTERFACE Hite ...

  8. Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,seria ...

  9. Serializable 接口与 Java 序列化与反序列化

    0. 序列化的意义 从内存到本地即为本地化或者在网络中进行传输,或叫序列化,持久化. 某 Java 类实现 Serializable 接口的目的是为了可持久化(简单理解为本地化),比如网络传输或本地存 ...

随机推荐

  1. 第一个python

    import MySQLdb import os,sys import string dto=os.getcwd()+"\\dto" dao=os.getcwd()+"\ ...

  2. Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息

    Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息 在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从 ...

  3. 分享Mvc3+NInject+EF+LigerUI权限系统Demo

    前段时间时不时看到有园友的分享权限系统,于是本人突发奇想,也想写一个玩玩,就利用晚上时间,陆陆续续花了一周多样子,写了如今这个权限系统,这个权限系统具有 组织结构.用户.角色.菜单,组织结构下挂用户, ...

  4. python schedule processor

    run some tasks which could look like CRON within linux/UNIX in python. Here's a demo which run on ub ...

  5. Eclipse代码自动提示设置

    以前百度过如何设置Eclipse代码自动提示,但是本人记性不好,所以把这个方法写成一篇日志,这样以后就不用百度了,直接看自己的博客就是了,而且还增加了自己博客的点击量.以下是从各个地方看到总结的方法: ...

  6. 在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序

    在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序 本贴首发于: http://xuekaiyuan.com/forum.php?mod=vie ...

  7. schemaeasyui实例:SSh结合Easyui实现Datagrid的分页显示

    查了好多资料,发现还是不全,干脆自己整理吧,最少保证在我的做法正确的,以免误导读者,也是给自己做个记载吧! 克日学习Easyui,发现非常好用,界面很雅观.将学习的心得在此写下,这篇博客写SSh结合E ...

  8. Android 开发环境 —— Eclipse 启动时报错:Error when loading the SDK

    简述: Eclipse 启动时报错:Error when loading the SDK 错误信息: Error when loading the SDK: Error: Error parsing  ...

  9. CSS3高级

    一.学习目标 二.box-sizing属性 语法:box-sizing: content-box|border-box|inherit box-sizing属性的用法: box-sizing属性可以为 ...

  10. 【C语言】字符串模块

    一.字符串简介 * 在Java中,一个字符串可以用String类型来存储 String s = "MJ"; C语言中没有String这种类型.其实字符串就是字符序列,由多个字符组成 ...