序列化与反序列化
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等。在网络传输过程中,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这个相反的过程又称为反序列化。
Java对象的序列化与反序列化
在Java中,我们可以通过多种方式来创建对象,并且只要对象没有被回收我们都可以复用该对象。但是,我们创建出来的这些Java对象都是存在于JVM的堆内存中的。只有JVM处于运行状态的时候,这些对象才可能存在。一旦JVM停止运行,这些对象的状态也就随之而丢失了。
但是在真实的应用场景中,我们需要将这些对象持久化下来,并且能够在需要的时候把对象重新读取出来。Java的对象序列化可以帮助我们实现该功能。
对象序列化机制(object serialization)是Java语言内建的一种对象持久化方式,通过对象序列化,可以把对象的状态保存为字节数组,并且可以在有需要的时候将这个字节数组通过反序列化的方式再转换成对象。对象序列化可以很容易的在JVM中的活动对象和字节数组(流)之间进行转换。
在Java中,对象的序列化与反序列化被广泛应用到RMI(远程方法调用)及网络传输中。
相关接口及类
Java为了方便开发人员将Java对象进行序列化及反序列化提供了一套方便的API来支持。其中包括以下接口和类:
java.io.Serializable
java.io.Externalizable
ObjectOutput
ObjectInput
ObjectOutputStream
ObjectInputStream
方式一:Serializable 接口
类通过实现 java.io.Serializable
接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。 (该接口并没有方法和字段,为什么只有实现了该接口的类的对象才能被序列化呢?)
当试图对一个对象进行序列化的时候,如果遇到不支持 Serializable 接口的对象。在此情况下,将抛出 NotSerializableException
。
如果要序列化的类有父类,要想同时将在父类中定义过的变量持久化下来,那么父类也应该集成java.io.Serializable
接口。
下面是一个实现了java.io.Serializable
接口的类
package com.hollischaung.serialization.SerializableDemos;
import java.io.Serializable;
/**
* Created by hollis on 16/2/17.
* 实现Serializable接口
*/
public class User1 implements Serializable {
private String name;
private int 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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
通过下面的代码进行序列化及反序列化
package com.hollischaung.serialization.SerializableDemos;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.*;
/**
* Created by hollis on 16/2/17.
* SerializableDemo1 结合SerializableDemo2说明 一个类要想被序列化必须实现Serializable接口
*/
public class SerializableDemo1 {
public static void main(String[] args) {
//Initializes The Object
User1 user = new User1();
user.setName("hollis");
user.setAge(23);
System.out.println(user);
//Write Obj to File
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(oos);
}
//Read Obj from File
File file = new File("tempFile");
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(file));
User1 newUser = (User1) ois.readObject();
System.out.println(newUser);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(ois);
try {
FileUtils.forceDelete(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//OutPut:
//User{name='hollis', age=23}
//User{name='hollis', age=23}
序列化工具类:不使用FFileInputStream 和FileOutputStream 使用ByteArrayInputStream ,ByteArrayOutputStream,这样更方便
public class SerializeUtil {
/*
* 序列化
* */
public static byte[] serizlize(Object object){
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(baos != null){
baos.close();
}
if (oos != null) {
oos.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
/*
* 反序列化
* */
public static Object deserialize(byte[] bytes){
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try{
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
}catch(Exception e){
e.printStackTrace();
}finally {
try {
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
}
二:ProtoBuff实现序列化(推荐)
什么是probobuf、作用是什么:
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。
protobuff序列化:告诉我对象的class,内部有schema来描述你的class是什么结构,class必须有get/set方法这种标准的类,而不是string等类
第一步:maven依赖
<!--prostuff序列化依赖-->
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.8</version>
</dependency>
完整代码:
public class ProtoBuffUtil {
public static <T> byte[] serialize(T t,Class<T> clazz) {
return ProtobufIOUtil.toByteArray(t, RuntimeSchema.createFrom(clazz),
LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
}
public static <T> T deSerialize(byte[] data,Class<T> clazz) {
RuntimeSchema<T> runtimeSchema = RuntimeSchema.createFrom(clazz);
T t = runtimeSchema.newMessage();
ProtobufIOUtil.mergeFrom(data, t, runtimeSchema);
return t;
}
}
public class App {
public static void main(String[] args) {
User user=new User("1","xiaobao","123456");
System.out.println("序列化");
byte[] data = SerializeUtils.serialize(user,User.class);
for (byte b : data) {
System.out.print(b);
}
System.out.println();
System.out.println("反序列化");
User user2 = SerializeUtils.deSerialize(data,User.class);
System.out.println(user2);
}
}
以上就是我们在编程中可以使用的序列化操作
更多关于Serializable的使用,请参考代码实例
方式一原文地址:http://www.hollischuang.com/archives/1150