http://www.cnblogs.com/fangfan/p/4094175.html

http://www.cnblogs.com/fangfan/p/4094175.html

前言:

Java序列化是Java技术体系当中的一个重要议题,序列化的意义在于信息的交换和存储,通常会和io、持久化、rmi技术有关(eg:一些orm框架会要求持久化的对象类型实现Serializable接口)。

本文将提供Java自带序列化机制和ProtoStuff的序列化(仅仅当作一种数据格式)的比较,从序列化的内容和特点来对二者进行比较。

结论:1,Java序列化对象时不需要通过属性的get set方法或其它无关序列化内部定义的方法(比如readObject,writeObject是内置的序列化方法),序列化也不需要get set方法支持,反序列化是构造对象的一种手段。

2,Java序列化时类型必须完全匹配(全路径类名+序列化id)。

3,Protostuff反序列化时并不要求类型匹配,比如包名、类名甚至是字段名,它仅仅需要序列化类型A 和反序列化类型B 的字段类型可转换(比如int可以转换为long)即可。

java.io.Serializable

标识一个对象需要系列化,该对象类型需要实现 Serializable 接口。关于序列化的认识,可以参考IBM社区的文章《Java序列化的高级认识》,本文直接拿该文档的结论。

1,序列化的类型和反序列化的类型的序列化ID必须一致(远程信息交换时)。

2,静态数据不会被序列化,Transient关键字修饰的字段不会被序列化。

3,对象序列化存储时,两次存储相同值对象会有优化(第二次对象写入会只存储引用)。

序列化技术

序列化的目的是进行数据存储和交换,依据这个概念,xml,json也是一种序列化的技术,只是他们似乎是一种容易分辨的序列化技术,而类似于protostuff或Java自身的序列化技术似乎略神秘。

那么,Java序列化技术与其它的序列化技术究竟有什么不同呢?下文将比较Java自身的序列化技术和protostuff做比较,窥探一二。

Protostuff

官网:https://code.google.com/p/protostuff/

Protostuff是基于大名鼎鼎的Google protobuff技术的Java版本,直接使用原生的protobuff是需要数据结构的预编译过程,需要编写.proto格式的配置文件,再通过protobuf提供的工具翻译成目标语言代码,而Protostuff动态支持了protobuff的预编译的过程。

下面的示例代码用于证明前言提出的结论

1,用于测试的实体(中括号内代表属性)

org.wit.ff.testmodel.SerializableUserA[String name, int age];

org.wit.ff.testmodel.SerializableUserB[String name, int age];

org.wit.ff.testmodel.ch.SerializableUserA[String name, int age];

org.wit.ff.testmodel.ch.SerializableUserC[String noneName, double noneAge];

org.wit.ff.testmodel.ch1.SerializableUserA[String name, int age, String firstName];

org.wit.ff.testmodel.ch1.SerializableUserB[String noneName, int noneAge];

org.wit.ff.testmodel.ch1.SerializableUserC[String noneName, int noneAge];

2,测试用例:

package org.wit.ff;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import org.junit.Test;
import org.wit.ff.testmodel.SerializableUserA;
import org.wit.ff.testmodel.SerializableUserB;
import org.wit.ff.util.ProtoStuffSerializerUtil; /**
*
* <pre>
* Java原生序列化机制.
* 与方法无关.
*
* 安全.
*
* </pre>
*
* @author F.Fang
* @version $Id: JavaSerializableDemo.java, v 0.1 2014年10月29日 上午12:48:11 F.Fang Exp $
*/
public class JavaSerializableDemo { /**
*
* <pre>
* Java自带序列化机制:检测对象序列化的内容.
* 序列化与方法无关,属性的赋值不通过方法.
* </pre>
*
*/
@Test
public void test1() {
SerializableUserA userA = new SerializableUserA("nobody",18);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(userA);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] userABytes = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(userABytes);
try {
ObjectInputStream ois = new ObjectInputStream(bais);
SerializableUserA userAS = (SerializableUserA) ois.readObject();
//System.out.println(userAS);
assertEquals(userA,userAS);
} catch (IOException e) {
e.printStackTrace();
assertFalse(true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
assertFalse(true);
}
} /**
*
* <pre>
* Java自带序列化机制:序列化和反序列化的类不同.
* (包括包和类名不同)
* java.lang.ClassCastException.
* </pre>
*
*/
@Test
public void test2() {
SerializableUserA userA = new SerializableUserA("nobody",18);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(userA);
} catch (IOException e) {
e.printStackTrace();
}
byte[] userABytes = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(userABytes);
try {
ObjectInputStream ois = new ObjectInputStream(bais);
org.wit.ff.testmodel.ch.SerializableUserA userA1 = (org.wit.ff.testmodel.ch.SerializableUserA) ois
.readObject();
System.out.println(userA1);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch(java.lang.ClassCastException e){
e.printStackTrace();
assertTrue(true);
}
} /**
*
* <pre>
* 使用protobuff执行序列化.
* </pre>
*
*/
@Test
public void test3(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
SerializableUserA userAs = ProtoStuffSerializerUtil.deserialize(arr, SerializableUserA.class);
//System.out.println(userAs);
assertNotNull(userAs);
assertEquals(userA.getAge(),userAs.getAge());
assertEquals(userA.getName(),userAs.getName());
} /**
*
* <pre>
* 使用Protobuff进行序列化.
* 序列化时的类和反序列化的类包路径不同.
* 反序列化成功.
* </pre>
*
*/
@Test
public void test4(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
org.wit.ff.testmodel.ch.SerializableUserA userAs = ProtoStuffSerializerUtil.deserialize(arr, org.wit.ff.testmodel.ch.SerializableUserA.class);
//System.out.println(userAs);
assertEquals(18,userAs.getAge());
assertEquals("nobody",userAs.getName());
} /**
*
* <pre>
* 使用Protobuff进行序列化.
* 序列化时的类和反序列化的类属性相同,类名不同.
* 反序列化成功.
* </pre>
*
*/
@Test
public void test5(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
SerializableUserB userBs = ProtoStuffSerializerUtil.deserialize(arr, SerializableUserB.class);
// System.out.println(userBs);
assertEquals(18,userBs.getAge());
assertEquals("nobody",userBs.getName());
} /**
*
* <pre>
* 使用Protobuff进行序列化.
* 序列化时的类的属性都包含在反序列化的类属性中.
* 反序列化成功.
* </pre>
*
*/
@Test
public void test6(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
org.wit.ff.testmodel.ch1.SerializableUserA userAs = ProtoStuffSerializerUtil.deserialize(arr, org.wit.ff.testmodel.ch1.SerializableUserA.class);
// System.out.println(userAs);
assertEquals(18,userAs.getAge());
assertEquals("nobody",userAs.getName());
} /**
*
* <pre>
* 使用Protobuff进行序列化.
* 序列化时的类和反序列化的类完全不同,属性名称也不相同,类型一致.
* 反序列化成功.
* </pre>
*
*/
@Test
public void test7(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
org.wit.ff.testmodel.ch1.SerializableUserB userBs = ProtoStuffSerializerUtil.deserialize(arr, org.wit.ff.testmodel.ch1.SerializableUserB.class);
System.out.println(userBs);
assertEquals("nobody",userBs.getNoneName());
assertEquals(18,userBs.getNoneAge());
} /**
*
* <pre>
* 使用Protobuff进行序列化.
* 序列化时的类和反序列化的类完全不同,属性名称也不相同.
* 各属性类型均不匹配.
* 针对属性
* 如果序列化类型为int 8
* 反序列化的类型为long
* 序列化成功.
* 反序列化的类型为double
* 反序列化不成功.
* eg1:
* SerializableUserA :age int,name String
* SerializableUserC : noneAge double, noneName String
* 反序列化不成功.
* SerializableUserC : noneAge long, noneName String
* 反序列化成功.
* </pre>
*
*/
@Test
public void test8(){
SerializableUserA userA = new SerializableUserA("nobody",18);
byte[] arr = ProtoStuffSerializerUtil.serialize(userA);
org.wit.ff.testmodel.ch1.SerializableUserC userCs = ProtoStuffSerializerUtil.deserialize(arr, org.wit.ff.testmodel.ch1.SerializableUserC.class);
System.out.println(userCs);
assertNotNull(userCs);
// 属性类型不匹配时发生异常!
try{
ProtoStuffSerializerUtil.deserialize(arr, org.wit.ff.testmodel.ch.SerializableUserC.class);
}catch(Exception e){
e.printStackTrace();
assertTrue(true);
} }
}
一段旅程,远去所有昨天的昨天,如记事本翻开新的一页,永远的不漏痕迹的把记忆藏在一片洁白中。然后绚烂的开始新的故事

Java序列化技术与Protobuff的更多相关文章

  1. Java序列化技术即将被废除!!!

    我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术.Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者 ...

  2. Java序列化技术

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化? Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象 ...

  3. 【转】java序列化技术

    转自:http://blog.csdn.net/yakihappy/article/details/3979373 Java 串行化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地 ...

  4. 深入分析Java Web技术内幕(修订版)

    阿里巴巴集团技术丛书 深入分析Java Web技术内幕(修订版)(阿里巴巴集团技术丛书.技术大牛范禹.玉伯.毕玄联合力荐!大型互联网公司开发应用实践!) 许令波 著   ISBN 978-7-121- ...

  5. Java 序列化的高级认识

    序列化 ID 问题 情境:两个客户端 A 和 B 试图通过网络传递对象数据,A 端将对象 C 序列化为二进制数据再传给 B,B 反序列化得到 C. 问题:C 对象的全类路径假设为 com.inout. ...

  6. 【Java】Java 序列化的高级认识

    如果你只知道实现 Serializable 接口的对象,可以序列化为本地文件.那你最好再阅读该篇文章,文章对序列化进行了更深一步的讨论,用实际的例子代码讲述了序列化的高级认识,包括父类序列化的问题.静 ...

  7. 深入理解JAVA序列化

    如果你只知道实现 Serializable 接口的对象,可以序列化为本地文件.那你最好再阅读该篇文章,文章对序列化进行了更深一步的讨论,用实际的例子代码讲述了序列化的高级认识,包括父类序列化的问题.静 ...

  8. java基础(十)-----Java 序列化的高级认识

    将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口,使用 ...

  9. Java序列化随记

    序列化简介: 程序中的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,因此需要Java序列化技术. Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制 ...

随机推荐

  1. 在Nginx中部署基于IP的虚拟主机

    一.虚拟主机概念 虚拟主机是在网络服务器上划分出一定的磁盘空间供用户放置站点.应用组件等,提供必要的站点功能.数据存放和传输功能.所谓虚拟主机,也叫"网站空间", 就是把一台运行在 ...

  2. mysql锁

    锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...

  3. JavaScript Engines

    http://openaphid.github.io/blog/2013/01/17/part-i-how-to-choose-a-javascript-engine-for-ios-and-andr ...

  4. Unreal模型文件调查

    http://en.wikipedia.org/wiki/UE_Viewer http://www.gildor.org/en/projects/umodel http://wiki.beyondun ...

  5. C# 6.0可能的新特性

    C# 6.0可能的新特性 1.主构造函数(Primary Constructors) 主构造函数给类中的变量赋值 Before public class Point { private int x, ...

  6. osharp3引入事务后操作结果类别的调整

    /// <summary> /// 表示业务操作结果的枚举, /// 对于业务务操作单元的影响只有二种状态, /// 成功,无变化: 操作将继续,事务将继续 /// 失败:将导致 操作被中 ...

  7. iOS开发工具-网络封包分析工具Charles

    转自唐巧的技术博客:http://blog.devtang.com/blog/2013/12/11/network-tool-charles-intr/ Charles是在Mac下常用的截取网络封包的 ...

  8. HDInsight 指定输出目录 insert overwrite

    基本语法 insert overwrite local directory '/example/demo/' select * from table; 可以格式化输出 insert overwrite ...

  9. 让Xcode的控制台支持LLDB类型的打印

    这个技巧个人认为非常有用 当Xcode在断点调试的时候,在控制台中输入 po self.view.frame 类似这样的命令会挂掉,不信可以亲自去试试(Xcode7 以后支持LLDB类型的打印) 那么 ...

  10. webservice报错Message part refundRequest was not recognized. (Does it exist in service WSDL?)

    最近在做一个支付的接口. 因为接口方使用webservice交互.  我只能去学习了下webservice 现在出了一个很古怪的问题~  我在请求他们url的时候, 返回给我找不到控制名错误 Mess ...