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. 生成秘钥文件 sn.exe(Strong Name Tool)

    Visual Studio 内置 Strong Name Tool, 我们直接运行"VS开发人员命令提示"就可以生成秘钥文件. 秘钥文件包含公钥和私钥. 来看这个例子: 在文件夹下 ...

  2. (自用)专业排版套装:CTeX + TeXStudio

    \documentclass[UTF8,landscape]{ctexart}%UTF8,ctexart中文支持,landscape横向版面 \usepackage{tikz}%画图 \usepack ...

  3. ecshop 获取某个商品的 所有订单信息 或者销量

    把一下代码放到 lib_main.php 1.统计某个下单商品的人数 function get_goods_ordernum($goods_id){ $sql = "select count ...

  4. webform membership2.0注入debug

    private IUserContract _UserService; public IUserContract UserService { get { if (_UserService == nul ...

  5. 自定义验证jquery.validate

    js中填写 $(function() { validateSysConfigForm(); jQuery.validator.addMethod("validateNum", fu ...

  6. CF456D A Lot of Games (字典树+DP)

    D - A Lot of Games CF#260 Div2 D题 CF#260 Div1 B题 Codeforces Round #260 CF455B D. A Lot of Games time ...

  7. JavaScript 学习笔记 -- String.trim + format

    最近仍在IE6徘徊,低版本的浏览器没有实现JavaScript 的trim() 和 format(). . 主要是这两个使用的比较多,先整理出来: 1.trim() -- 去除字符串中开始和结尾部分, ...

  8. BufferedReader readLine()方法

    控制台输入字符串之后回车,后台接收传来的字符串,代码如下: import java.io.BufferedReader; import java.io.IOException; import java ...

  9. 基本select语句的生命周期

    (1) 客户端sqlserver网络接口通过一种网络协议(可以是共享内存:简单高速,客户端和sql server在同一台计算机默认连接方式:TCP/IP:访问sql server最常用的一种协议,客户 ...

  10. 黑客攻防技术宝典Web实战篇(一)Web应用程序技术基础

    在开展Web应用程序渗透测试之前请先了解下面列出的这些内容,如果不是很懂的话,请读David Gourley & Brian Totty的HTTP权威指南也叫HTTP:The Definiti ...