Java对象表示方式2:XStream实现对对象的XML化

上一篇文章讲到了使用Java原生的序列化的方式来表示一个对象。总结一下这种对象表示方式的优缺点:

1、纯粹的Java环境下这种方式可以很好地工作,因为它是Java自带的,也不需要第三方的Jar包的支持

2、多语言环境下,使用Java序列化方式进行存储后,很难用其他语言还原出结果

3、占用的字节数比较大,而且序列化、反序列化效率也不高

前面也提到过,对象表示有各种各样的方式,序列化只是其中的一种而已。表示一个对象的目的无非就是为了对象<---->IO之 间相互认识,至于怎么认识,那就有很多选择了。除了之前讲过的序列化,还可以选择将数据JSON化、XML化。当前也有比较好用的序列化工具,比如 Google的protobuf。这篇文章主要想写一下对对象进行XML化,使用的是XStream。至于为什么选择写XStream,因为工作用,呵 呵。

利用XStream表示一个对象

XStream 就是一种Java对象和XML之间相互转换的工具,没有什么可以特别介绍的,XStream提供了所有的基础类型、数组、集合等类型直接转换的支持。 XStream中的核心类就是XStream类,一般来说熟悉这个类就够用了。使用XStream需要用到两个第三方jar包,我工程里面使用的xstream-1.4.jarkxml2.jar。一开始我在玩XStream以为只需要前一个jar包就可以了,结果运行的时候各种错误,所以这里要注意一下。首先写一个最简单的程序:

 1 public class XmlObject
 2 {
 3     private int       count;
 4     private double    price;
 5     private String    phone;
 6
 7     public XmlObject(int count, double price, String phone)
 8     {
 9         this.count = count;
10         this.price = price;
11         this.phone = phone;
12     }
13
14     public String toString()
15     {
16         return "count = " + count + ", price = " + price + ", phone = " + phone;
17     }
18 }

1 public static void main(String[] args)
2 {
3     XStream xs = new XStream();
4     XmlObject xo = new XmlObject(10, 10.5, "110");
5     String str = xs.toXML(xo);
6     System.out.println(str);
7 }

看一下运行结果:

<com.xrq.test.XmlObject>
  <count>10</count>
  <price>10.5</price>
  <phone>110</phone>
</com.xrq.test.XmlObject>

是的,这么简单,就把一个对象表示出来了。这时候,想怎么操作这个str都无所谓了,可以用一个FileWriter把这个str存入磁盘,也可以用一个HttpClient传输这串str进行网络通信。

设置一下别名

OK,看到上面这串输出,可能有些人不爽了,“com.xrq.test.XmlObject”这么麻烦,能不能表示地简单点啊?当然可以,而且不仅可以对对象重命名,对象中的属性也可以:

 1 public static void main(String[] args)
 2 {
 3     XStream xs = new XStream();
 4     XmlObject xo = new XmlObject(10, 10.5, "110");
 5     xs.alias("XmlObject", XmlObject.class);
 6     xs.aliasField("Count", XmlObject.class, "count");
 7     xs.aliasField("Price", XmlObject.class, "price");
 8     xs.aliasField("Phone", XmlObject.class, "phone");
 9     String str = xs.toXML(xo);
10     System.out.println(str);
11 }

看一下运行结果:

<XmlObject>
  <Count>10</Count>
  <Price>10.5</Price>
  <Phone>110</Phone>
</XmlObject>

看到,对象名变了,对象中的属性名也变化了。

XStream支持数组和集合

之前说过,XStream不仅支持基本数据类型,也支持数组、集合,把程序修改一下再看一下:

 1 public class XmlObject
 2 {
 3     private int[]                 counts;
 4     private List<String>          phones;
 5     private Map<String, Date>     calendar;
 6
 7     public XmlObject(int[] counts, List<String> phones, Map<String, Date> calendar)
 8     {
 9         this.counts = counts;
10         this.phones = phones;
11         this.calendar = calendar;
12     }
13
14     public String toString()
15     {
16         return "count = " + counts + ", phones = " + phones + ", calendar = " + calendar;
17     }
18 }

 1 public static void main(String[] args)
 2 {
 3     int[] counts = {10, 11, 12};
 4     List<String> phones = new ArrayList<String>();
 5     phones.add("110");
 6     phones.add("119");
 7     phones.add("120");
 8     Map<String, Date> calendar = new HashMap<String, Date>();
 9     calendar.put("1", new Date());
10     calendar.put("2", new Date());
11     XStream xs = new XStream();
12     XmlObject xo = new XmlObject(counts, phones, calendar);
13     xs.alias("XmlObject", XmlObject.class);
14     xs.aliasField("Count", XmlObject.class, "counts");
15     xs.aliasField("Phones", XmlObject.class, "phones");
16     xs.aliasField("Calendar", XmlObject.class, "calendar");
17     String str = xs.toXML(xo);
18     System.out.println(str);
19 }

看一下运行结果

+

看到string、date这两个开头字母都是小写的有点不爽?没关系,依样画葫芦,main函数里面加上这两句就可以了

xs.alias("String", String.class);

xs.alias("Date", Date.class);

XML转换成Java对象

回归前面最简单的那个XmlObject,看一下把XML转换为Java对象,也很简单,利用fromXml()方法就可以了。自己构造一个xml字符串:

1 public static void main(String[] args)
2 {
3     XStream xs = new XStream();
4     String xmlStr = "<com.xrq.test.XmlObject><count>10</count><price>10.5</price><phone>110</phone></com.xrq.test.XmlObject>";
5     XmlObject xo = (XmlObject)xs.fromXML(xmlStr);
6     System.out.println(xo);
7 }

运行结果就不贴了,就是XmlObject三个属性的toString()而已。注意这里用的没有alias过的“com.xrq.test.XmlObject”, 要是直接用“XmlObject”会报 “com.thoughtworks.xstream.mapper.CannotResolveClassException”这个异常。解决方案很简 单,第5行前面加上xs.alias("XmlObject", XmlObject.class);就好了。

后记

文章主要写了对于XStream的使用,一般来说,XStream用到这个程度也 就够了。XStream使用非常容易,而且XML化之后的数据可读性强。不过在github上看到了一篇文章https://github.com /eishay/jvm-serializers/wiki,看得出XML的缺点主要在于还是解析的时候效率低了一些,而且为了可读性,XML也引入了一 些冗余的文本信息从而造成了一定的空间开销。但是,无论如何,操作量不大的场景下 ,个人还是推荐使用XStream。

时间: 2024-11-08 21:34:14

Java对象表示方式2:XStream实现对对象的XML化的相关文章

以对象的方式来访问xml数据表(二)

为什么要以对象的方式来访问xml数据表? 还记得,自己是在一次完成师兄布置的任务时接触到了xml,那时候需要用xml来作为数据文件,保存一个简单的图书管理系统的数据.于是就知道了,可以用xml文件来保存数据(而且比用简单的文本文件保存数据规范的多,在访问与读取数据上面都十分方便),就这样使用xml的征程开始了. 自己做的第一个WPF桌面应用程序——备忘录,就是用xml文件作为数据库.而且那个时候考虑到以后可能会经常使用到xml文件作为数据库,于是乎就写了一个专门用于访问xml文件的动态链接库,这

JS中对象继承方式

JS对象继承方式 摘自<JavaScript的对象继承方式,有几种写法>,作者:peakedness 链接:https://my.oschina.net/u/3970421/blog/2872629 方式一:对象冒充 原理:构造函数使用this关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使Parent构造函数称为Children的方法,然后调用它.Children会收到Parent的构造函数中定义的属性和方法. *** //父类构造函数 var P

Java对象表示方式1:序列化、反序列化和transient关键字的作用

http://www.cnblogs.com/xrq730/p/4821958.html 平时我们在Java内存中的对象,是无 法进行IO操作或者网络通信的,因为在进行IO操作或者网络通信的时候,人家根本不知道内存中的对象是个什么东西,因此必须将对象以某种方式表示出来,即 存储对象中的状态.一个Java对象的表示有各种各样的方式,Java本身也提供给了用户一种表示对象的方式,那就是序列化.换句话说,序列化只是表示对 象的一种方式而已.OK,有了序列化,那么必然有反序列化,我们先看一下序列化.反序

java 27 - 2 反射之 反射的概述以及获取Class文件对象的方式

反射: JAVA语言的反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 如何解剖一个类: 要想解剖一个类,必须先要获取到该类的字节码文件对象. 而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象. 通俗的来说: 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法

JAVA实现 springMVC方式的微信接入、实现消息自动回复

前段时间小忙了一阵,微信公众号的开发,从零开始看文档,踩了不少坑,也算是熬过来了,最近考虑做一些总结,方便以后再开发的时候回顾,也给正在做相关项目的同学做个参考. 思路 微信接入:用户消息和开发者需要的事件推送都会通过微信方服务器发起一个请求,转发到你在公众平台配置的服务器url地址,微信方将带上signature,timestamp,nonce,echostr四个参数,我们自己服务器通过拼接公众平台配置的token,以及传上来的timestamp,nonce进行SHA1加密后匹配signatu

JAVA实现 springMVC方式的微信接入、实现简单的自动回复

前端时间小忙了一阵,微信公众号的开发,从零开始看文档,踩了不少坑,也算是熬过来了,最近考虑做一些总结,方便以后再开发的时候回顾,也给正在做相关项目的同学做个参考. 其实做过一遍之后会发现也不难,大致思路:用户消息和开发者需要的事件推送都会通过微信方服务器发起一个请求,转发到你在公众平台配置的服务器url地址,微信方将带上signature,timestamp,nonce,echostr四个参数,我们自己服务器通过拼接公众平台配置的token,以及传上来的timestamp,nonce进行SHA1

JAVA学习第三十三课(常用对象API)- 集合框架(一)

数字有很多用数组存,对象有很多就要用集合存 但是数组是固定长度的,集合是可变长度的 集合的由来: 对象用来封装特有数据,对象多了需要存储,如果对象个数不确定,就需要使用集合容器来存储 集合的特点: 1.用于存储对象的容器 2.长度可变 3.集合中不可存储基本数据类型 对于集合体系,的最顶层存储的是该体系中所有的共性内容,Collection,同继承一样,看顶层,用底层 java.uitil包中的Cellection 集合容器因为内部的数据不同,有多种具体容器,不断向上抽取,就形成了集合框架 整个

Java 并发编程(二)对象的不变性和安全的发布对象

一.不变性 满足同步需求的另一种方法是使用不可变对象(Immutable Object).到目前为止,我们介绍了许多与原子性和可见性相关的问题,例如得到失效数据,丢失更新操作或光查到某个对象处于不一致的状态等等,都与多线程视图同时访问同一个可变的状态相关.如果对象的状态不会改变,那么这些问题与复杂性也就自然消失了. 如果某个对象在被创建后其状态就不能被修改,那么这个对象就被成为不可变对象.线程安全型是不可变对象的固有属性之一,他们的不变性条件是由构造函数创建的,只要他们的状态不改变,那么这些不变

Java Map遍历方式的选择

1. 阐述 对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多.理由是:entrySet方法一次拿到所有key和value的集合:而keySet拿到的只是key的集合,针对每个key,都要去Map中额外查找一次value,从而降低了总体效率.那么实际情况如何呢? 为了解遍历性能的真实差距,包括在遍历key+value.遍历key.遍历value等不同场景下的差异,我试着进行了一些对比测试. 2. 对比测试 一开始只进行了简单的测试,但结果却表明k