序列化与反序列化总结(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 接口的目的是为了可持久化(简单理解为本地化),比如网络传输或本地存 ...
随机推荐
- Topics
Topics Introduction (starting with old devices) How to handle a new Firmware How to set up your Mac ...
- [转]Apple iPod, iPhone (2g, 3g), iPad Dock connector pinout
Pin Signal Description Apple pin numbering* 1 GND Ground (-), internally connected with Pin 2 on iPo ...
- Java并发性和多线程
Java并发性和多线程介绍 java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题, ...
- 原生Js封装的弹出框-弹出窗口-页面居中-多状态可选
原生Js封装的弹出框-弹出窗口-页面居中-多状态可选 实现了一下功能: 1.title可自定义 可拖拽 2.width height可以自定义 3.背景遮罩和透明度可以自定义 4.可以自己编辑弹出 ...
- javascript继承的写法
原文链接:http://js8.in/698.html. 构造函数继承: 第一种方法是使用prototype属性: 这里也可以直接Child.prototype=new P();考虑到P构造函数的参数 ...
- 依赖注入(DI)和Ninject
[ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject 本文目录: 1.为什么需要依赖注入 2.什么是依赖注入 3.使用NuGet安装库 4.使用Ninject的一般步骤 5. ...
- Java中Path和CLASSPATH的正确配置
JAVA_HOME: D:\soft\study\jdk1.7.0_01 JAVA_HOME里配置的是我们jdk安装的路径,这样配置就好.如果你是要用到JAVA_HOME的话,那就不要在JAVA_HO ...
- JDBC连接数据库(MySQL)
package com.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSe ...
- openlayers 加载瓦片详解 一
在这先说点题外话,本人在研究webgl 三维球过程中惊人发现,openlayers 的开发人员也在研究webgl并经证实他们也正在研发基于 webgl的三维gis开源平台,这可能是首个开源的三维平台, ...
- tensorflow与kubernetes/docker结合使用实践
tensorflow tensorflow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流 ...