前言

上一篇文章讲到了使用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包就可以了,结果运行的时候各种错误,所以这里要注意一下。首先写一个最简单的程序:

 public class XmlObject
{
private int count;
private double price;
private String phone; public XmlObject(int count, double price, String phone)
{
this.count = count;
this.price = price;
this.phone = phone;
} public String toString()
{
return "count = " + count + ", price = " + price + ", phone = " + phone;
}
}
 public static void main(String[] args)
{
XStream xs = new XStream();
XmlObject xo = new XmlObject(10, 10.5, "110");
String str = xs.toXML(xo);
System.out.println(str);
}

看一下运行结果:

<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”这么麻烦,能不能表示地简单点啊?当然可以,而且不仅可以对对象重命名,对象中的属性也可以:

 public static void main(String[] args)
{
XStream xs = new XStream();
XmlObject xo = new XmlObject(10, 10.5, "110");
xs.alias("XmlObject", XmlObject.class);
xs.aliasField("Count", XmlObject.class, "count");
xs.aliasField("Price", XmlObject.class, "price");
xs.aliasField("Phone", XmlObject.class, "phone");
String str = xs.toXML(xo);
System.out.println(str);
}

看一下运行结果:

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

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

XStream支持数组和集合

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

 public class XmlObject
{
private int[] counts;
private List<String> phones;
private Map<String, Date> calendar; public XmlObject(int[] counts, List<String> phones, Map<String, Date> calendar)
{
this.counts = counts;
this.phones = phones;
this.calendar = calendar;
} public String toString()
{
return "count = " + counts + ", phones = " + phones + ", calendar = " + calendar;
}
}
 public static void main(String[] args)
{
int[] counts = {10, 11, 12};
List<String> phones = new ArrayList<String>();
phones.add("110");
phones.add("119");
phones.add("120");
Map<String, Date> calendar = new HashMap<String, Date>();
calendar.put("1", new Date());
calendar.put("2", new Date());
XStream xs = new XStream();
XmlObject xo = new XmlObject(counts, phones, calendar);
xs.alias("XmlObject", XmlObject.class);
xs.aliasField("Count", XmlObject.class, "counts");
xs.aliasField("Phones", XmlObject.class, "phones");
xs.aliasField("Calendar", XmlObject.class, "calendar");
String str = xs.toXML(xo);
System.out.println(str);
}

看一下运行结果

<XmlObject>
<Count>
<int>10</int>
<int>11</int>
<int>12</int>
</Count>
<Phones>
<string>110</string>
<string>119</string>
<string>120</string>
</Phones>
<Calendar>
<entry>
<string>2</string>
<date>2015-09-20 08:23:13.665 UTC</date>
</entry>
<entry>
<string>1</string>
<date>2015-09-20 08:23:13.665 UTC</date>
</entry>
</Calendar>
</XmlObject>

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

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

XML转换成Java对象

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

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

运行结果就不贴了,就是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。

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

  1. JAVA - 序列化的方式

    JAVA - 序列化的方式 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读 ...

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

    为什么要以对象的方式来访问xml数据表? 还记得,自己是在一次完成师兄布置的任务时接触到了xml,那时候需要用xml来作为数据文件,保存一个简单的图书管理系统的数据.于是就知道了,可以用xml文件来保 ...

  3. JS中对象继承方式

    JS对象继承方式 摘自<JavaScript的对象继承方式,有几种写法>,作者:peakedness 链接:https://my.oschina.net/u/3970421/blog/28 ...

  4. java对象表示方式--XStream

    对象表示有各种各样的方式,序列化只是其中的一种而已.表示一个对象的目的无非就是为了对象<---->IO之间相互认识,至于怎么认识,那就有很多选择了.除了之前讲过的序列化,还可以选择将数据J ...

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

    平时我们在Java内存中的对象,是无法进行IO操作或者网络通信的,因为在进行IO操作或者网络通信的时候,人家根本不知道内存中的对象是个什么东西,因此必须将对象以某种方式表示出来,即存储对象中的状态.一 ...

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

    反射: JAVA语言的反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调 ...

  7. 基于Java的三种对象持久化方式

    1:序列化技术: 序列化的过程就是将对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,可以通过管道或线程读取,或通过网络连接将对象 ...

  8. Java对象表示方式1:序列化、反序列化的作用

    1.序列化是的作用和用途 序列化:把对象转换为字节序列的过程称为对象的序列化. 反序列化:把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存 ...

  9. Java反射02 : Class对象获取的三种方式和通过反射实例化对象的两种方式

    1.Class对象获取的三种方式 本文转载自:https://blog.csdn.net/hanchao5272/article/details/79361463 上一章节已经说过,一般情况下,Jav ...

随机推荐

  1. Servlet知识

    1.Servlet概述 2.编写Servlet的开发步骤a.建立标准的JavaWeb应用目录FirstAppWEB-INFclasseslibweb.xmlb.编写一个类,实现javax.servle ...

  2. labview学习_入门篇(一)

    写在前面的话: 在上大学的时候,实验室的老师推荐用labview工具编写上位机软件,当时不想用labview,感觉不写代码心里不踏实,后来用vb和matalb开发了上位机软件.但现在由于部门的几款工具 ...

  3. PHP使用内置函数生成图片的方法详解

    原文地址:http://www.poluoluo.com/jzxy/201605/475301.html 本文实例讲述了PHP使用内置函数生成图片的方法.分享给大家供大家参考,具体如下: 第一步:创建 ...

  4. 关于Linux 下 Mysql 远程访问时出现的Access denied for user '用户名'@'IP地址' (using password:NO)

    大概是因为MySQL不允许远程访问时候不带密码吧,所以还是设定一个密码 如下这样做: 打开终端 ,即terminal的那个(RedHat5.x为例 在左上角(可能会移位)那个带着红帽的家伙点击,--- ...

  5. python 使用字符串名调用类以及调用类方法名

    在python中,有时调用者仅知道类名和类方法,不负责实际的函数调用,而是将要调用的类名和类方法告诉一个中间函数,由中间函数负责实际调用函数.中间函数需以被告知的字符串调用类和类方法.         ...

  6. Oracle sql语句练习

    --1.选择在部门 30 中员工的所有信息 ; --2.列出职位为(MANAGER)的员工的编号,姓名 select EMPNO, ENAME from emp where job='MANAGER' ...

  7. JAVA单例的三种实现方式

    1. public class MySingleton { private MySingleton() {} private MySingleton instance = new MySingleto ...

  8. 编译系统中的LR与LL理解

    编译原理:LL(1),LR(0),SLR(1),LALR(1),LR(1)对比 LL(1)定义:一个文法G是LL(1)的,当且仅当对于G的每一个非终结符A的任何两个不同产生式 A→α|β,下面的条件成 ...

  9. VC CComboBox用法总结

    VC每日一练,虽然简单,不动手试一下不能真正记住. 大气象 CComboBox *comboBox=(CComboBox*)GetDlgItem(IDC_COMBO1); comboBox->I ...

  10. java-API中的常用类,新特性之-泛型,高级For循环,可变参数

    API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...