序列化,将对象的状态信息转换为可以存储或传输的形式的过程。
在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
一、概念 Java序列化是指把Java对象转换为字节序列的过程;
而Java反序列化是指把字节序列恢复为Java对象的过程。
二、用途 1、实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)
2、通过序列化对象在网络中传递对象。
3、通过序列化对象在进程间传递对象。
三、Serializable接口实现序列化 Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。
对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。
Ⅰ、Android Studio自动生成SerizlVersionUID: 1、File -> Settings… -> Editor -> Inspections -> Serialization issues -> Serializable class without ‘serialVersionUID‘(选中)
2、进入实现了Serializable中的类,选中类名,Alt+Enter弹出提示,然后直接导入完成.
package org.raphets.democollection; import java.io.Serializable; public class Dog implements Serializable{ private static final long serialVersionUID = -2457171891775313955L; private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Ⅱ、利用Serializable保存对象到本地 package org.raphets.democollection; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); storageSerializableData(); getSerializableData(); } /** * 存储Serializable数据到本地 */ private void storageSerializableData() { List<Dog> mDogs = new ArrayList<>(); Dog dog1 = new Dog("a", 3); Dog dog2 = new Dog("b", 4); Dog dog3 = new Dog("c", 2); mDogs.add(dog1); mDogs.add(dog2); mDogs.add(dog3); FileOutputStream fos = null; ObjectOutputStream oos = null; try { File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "dogs.dat"); if (!file.exists()) { file.createNewFile(); } fos = new FileOutputStream(file.toString()); oos = new ObjectOutputStream(fos); oos.writeObject(mDogs); } catch (Exception e) { Log.i("TAG",e.toString()); } finally { try { if (oos != null) oos.close(); if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 读取本地的Seriablizable数据 */ private void getSerializableData() { FileInputStream fis=null; ObjectInputStream ois=null; File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "dogs.dat"); if (file.exists()){ try { fis=new FileInputStream(file.toString()); ois=new ObjectInputStream(fis); List<Dog> mDogs= (List<Dog>) ois.readObject(); for (Dog dog:mDogs){ Log.i("Dog",dog.getName()); } } catch (Exception e) { e.printStackTrace(); } } } }
四、Parcelable接口实现序列化 Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
实现Parcelable接口主要可以分为一下几步:
1)implements Parcelable。
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从Parcel容器获取数据。
3)重写describeContents方法,内容接口描述,默认返回0即可。
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator 。 注意:若将Parcel看成是一个流,则先通过writeToParcel把对象写到流里面,再通过createFromParcel从流里读取对象,因此类实现的写入顺序和读出顺序必须一致。
package org.raphets.democollection; import android.os.Parcel; import android.os.Parcelable; public class Dog implements Parcelable{ private String name; private int age; protected Dog(Parcel in) { name = in.readString(); age = in.readInt(); } public Dog(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static final Creator<Dog> CREATOR = new Creator<Dog>() { @Override public Dog createFromParcel(Parcel in) { return new Dog(in); } @Override public Dog[] newArray(int size) { return new Dog[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(name); parcel.writeInt(age); } }
五、Parcelable和Serializable的区别: 1、在使用内存的时候Parcelable比Serializable的性能高。
2、Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC(内存回收)。
3、Parcelable不能使用在将对象存储在磁盘上这种情况,因为在外界的变化下Parcelable不能很好的保证数据的持续性。
4、在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上
5、Parcelable是以Ibinder作为信息载体的.在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable
六、如何选择 Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据。
而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable。
Android不同版本Parcelable可能不同,所以在序列化到存储设备或者网络传输方面还是尽量选择Serializable接口。