序列化与反序列化总结(Serializable和Parcelable)
序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。
在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)的更多相关文章
- 序列化、反序列化(Serializable特性)
//需要被实例化的类 using System.Collections; using UnityEngine; [Serializable] public class SerializableClas ...
- Android序列化之Serializable和Parcelable
PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...
- 序列化Serializable和Parcelable
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录下序列化Serializable和Parcelable的使用方法. Android中Intent如果要传递类对象,可以通过两 ...
- Android中Serializable和Parcelable序列化对象详解
学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.P ...
- 【Android - IPC】之Serializable和Parcelable序列化
1.序列化的目的 (1)永久的保存对象数据(将对象数据保存到文件或磁盘中): (2)通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的,因此序列化的目的是将对象数据 ...
- Java序列化与反序列化(Serializable)
Java序列化与反序列化(Serializable) 特别注意: 1.要序列化的类必须实现Serializable借口 2.在反序列化(读取对象)的时候必须额外捕获EOFException 3.序列化 ...
- 使用Serializable接口进行JAVA的序列化和反序列化
OBJECT STREAMS – SERIALIZATION AND DESERIALIZATION IN JAVA EXAMPLE USING SERIALIZABLE INTERFACE Hite ...
- Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,seria ...
- Serializable 接口与 Java 序列化与反序列化
0. 序列化的意义 从内存到本地即为本地化或者在网络中进行传输,或叫序列化,持久化. 某 Java 类实现 Serializable 接口的目的是为了可持久化(简单理解为本地化),比如网络传输或本地存 ...
随机推荐
- 第一个python
import MySQLdb import os,sys import string dto=os.getcwd()+"\\dto" dao=os.getcwd()+"\ ...
- Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息
Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息 在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从 ...
- 分享Mvc3+NInject+EF+LigerUI权限系统Demo
前段时间时不时看到有园友的分享权限系统,于是本人突发奇想,也想写一个玩玩,就利用晚上时间,陆陆续续花了一周多样子,写了如今这个权限系统,这个权限系统具有 组织结构.用户.角色.菜单,组织结构下挂用户, ...
- python schedule processor
run some tasks which could look like CRON within linux/UNIX in python. Here's a demo which run on ub ...
- Eclipse代码自动提示设置
以前百度过如何设置Eclipse代码自动提示,但是本人记性不好,所以把这个方法写成一篇日志,这样以后就不用百度了,直接看自己的博客就是了,而且还增加了自己博客的点击量.以下是从各个地方看到总结的方法: ...
- 在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序
在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序 本贴首发于: http://xuekaiyuan.com/forum.php?mod=vie ...
- schemaeasyui实例:SSh结合Easyui实现Datagrid的分页显示
查了好多资料,发现还是不全,干脆自己整理吧,最少保证在我的做法正确的,以免误导读者,也是给自己做个记载吧! 克日学习Easyui,发现非常好用,界面很雅观.将学习的心得在此写下,这篇博客写SSh结合E ...
- Android 开发环境 —— Eclipse 启动时报错:Error when loading the SDK
简述: Eclipse 启动时报错:Error when loading the SDK 错误信息: Error when loading the SDK: Error: Error parsing ...
- CSS3高级
一.学习目标 二.box-sizing属性 语法:box-sizing: content-box|border-box|inherit box-sizing属性的用法: box-sizing属性可以为 ...
- 【C语言】字符串模块
一.字符串简介 * 在Java中,一个字符串可以用String类型来存储 String s = "MJ"; C语言中没有String这种类型.其实字符串就是字符序列,由多个字符组成 ...