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

在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. 批量转换cue文件编码

    之前在网上下载的无损(flac.ape),好多都是整盘的,也就是说一个flac或ape文件搭配一个cue分轨文件,这个文件记录着在不同时间段是哪一首歌曲. 由于之前的操作都是在windows下进行的, ...

  2. SOCKET网络编程细节问题3

    SOCKET网络编程快速上手(二)——细节问题(3) 3.SIGPIPE问题 人怕牺牲,我们写的程序也一样,人有死不瞑目,程序又何尝不是?程序跑着跑着,突然就崩掉了.好一点的牺牲前告诉你些打印,差点的 ...

  3. 关于 HttpModule配置问题

    在经典模式下,配置到System.web节点 在IIS7以上的集成模式下,要配置到<system.webServer>节点 否则会出现类似一下的错误: 具体配置如下: <config ...

  4. Klockwork告警常见错误

    下面列举的是Klockwork告警中常见的告警形式,这些情况在编译阶段都不会报出来语法上的错误,并且在运行阶段执行到的概率很小.但是在某些场景下一旦执行到了这些语句, 很可能引起进程的跑飞和挂起.   ...

  5. 国外大师给PHP初学者的8条建议

    学习一门新语言可能会是一件很艰巨的任务,最好的办法就是借鉴前辈的经验已达到事半功倍,下面就是为php新手们准备的一些经验餐. 1.从OOP开始Naramore是SourceForge员工以及PHPWo ...

  6. Android数据存储汇总

    1.sharedpreference,存储简单的信息,比如用户名,密码 package com.google.datastore.sharep; import android.app.Activity ...

  7. C语言之冒泡排序

    冒泡排序: 1). 简介 其实就是把一个数组的元素,按照从小到大(从大到小)得顺序,重新排列起来,这种排序就叫冒泡排序 例: int nums[5] = {5,4,3,2,1}; //经过排序后 下标 ...

  8. C语言之带有返回值的函数

    带有返回值的函数 语法: 类型 函数名(参数列表){ 函数体; return 数据; } 例: int getSum(int num1,int num2){ int sum = num1 + num2 ...

  9. CKPlayer 只调用HTML5播放器时全屏问题 这只是Chrome浏览器的渲染bug

    如题,在系统中使用CKPlayer播放器,一切顺利,偶然发现没有全屏按钮, 正常的全屏按钮是这样的: 经过一步步调试,发现问题出在iframe, 当视频页面在iframe内时,全屏按钮不显示了,这个和 ...

  10. SqlServer创建数据表描述及列描述信息

    SqlServer创建数据表描述及列描述信息 Intro Q: 为什么要创建描述信息? A: 鼠标悬停在对应表和列上时,会出现描述信息,可以提高工作的效率,借助工具我们根据数据表可以生成Model,可 ...