Java的序列化是如何工作的以及何时应该使用它来代替其他持久化技术?
我一直在努力学习更多东西,通常testingJava的序列化工作和个人项目,我必须说,我知道得越多,我越喜欢它。 这可能是由错误信息引起的,所以这就是我为什么要问你这两件事:
1:在字节级,序列化如何知道如何将序列化的值与某个类匹配?
我的问题之一就是我用ArrayList包含值“one”,“two”,“three”做了一个小testing。 在序列化之后,字节数组占据了78个字节,这对于如此less量的信息(19 + 3 + 3 + 4字节)似乎非常有用。 当然,有一定的开销,但这导致了我的第二个问题:
2:序列化可以被认为是坚持对象的好方法吗? 现在显然如果我使用一些自制的XML格式的持久性数据将是这样的
<object> <class="java.util.ArrayList"> <!-- Object array inside Arraylist is called elementData --> <field name="elementData"> <value>One</value> <value>Two</value> <value>Three</value> </field> </object>
它像XML一般,有点臃肿,需要138个字节(没有空格,就是这样)。 在JSON中也是一样的
{ "java.util.ArrayList": { "elementData": [ "one", "two", "three" ] } }
这是75个字节,因此已经比Java的序列化略小。 有了这些基于文本的格式,当然显而易见的是必须有一种方法来将您的基本数据表示为文本,数字或两者的任意组合。
所以要回顾一下,序列化是如何在字节/比特级别上工作的,什么时候应该使用,什么时候不应该使用,除了在Java中标准化之外,还有什么是序列化的真正好处呢?
我会亲自尝试避免Java的“内置”序列化:
- 它不能移植到其他平台
- 这不是非常有效
- 这是脆弱的 – 让它处理一个类的多个版本有点棘手。 除非你小心,否则即使改变编译器也会破坏序列化。
有关实际字节的含义的详细信息,请参阅Java对象序列化规范 。
有多种select,例如:
- XML和JSON,正如你所展示的(当然有各种XML风格)
- YAML
- Facebook的Thrift (RPC以及序列化)
- Google协议缓冲区
- Hessian (Web服务以及序列化)
- 阿帕奇Avro
- 您自己的自定义格式
(免责声明:我为Google工作,我正在为C#做一个协议缓冲区端口作为我的20%的项目,所以我认为这是一个很好的技术:)
由于显而易见的原因,跨平台格式几乎总是比特定于平台的格式更具限制性 – 例如,协议缓冲区有一组非常有限的本地types – 但互操作性可能非常有用。 您还需要考虑版本控制的影响,以及向前和向后兼容性等。文本格式通常是可手动编辑的,但在空间和时间上往往效率较低。
基本上,你需要仔细看看你的要求。
序列化的主要优点是使用起来非常简单,速度相对较快,并保留了实际的Java对象网格。
但是您必须认识到,这并不是要用于存储数据,而是主要作为不同JVM实例通过使用RMI协议的networking进行通信的一种方式。
请参阅Java对象序列化stream协议 ,以获取用于序列化对象的文件格式和语法的描述。
就我个人而言,我认为内置的序列化是可以接受的,以保持短期的数据(例如,将会话对象的状态存储在http请求之间),这与您的应用程序之外无关。
对于具有更长的活动时间或应该在应用程序之外使用的数据,我会坚持要么到数据库中,要么至less使用更常用的格式…
我在一个月前遇到了这个困境(见我问的问题 )。
我从中学到的主要教训是只有在必要时才使用Java序列化,如果没有其他选项的话。 像乔恩说的那样,它已经是倒闭了,而其他的序列化技术更容易,更快,更便携。
序列化意味着您可以将您的结构化数据放入您的类中,并保存为字节码的平面顺序。
您通常应该使用除buildin java-method以外的其他技术,只是开箱即用,但是如果您的序列化类中将来有更改内容或更改顺序,则会因为无法加载而出现问题他们正确。
Java对象序列化(Java Object Serialization,JOS)的优势在于它正常工作。 这里也有一些与JOS相同的工具,但是使用XML格式而不是二进制格式。
关于长度:JOS在开始时写入一些类信息,而不是作为每个实例的一部分 – 例如全部字段名称被logging一次,并且名称列表的索引被用于该类的实例。 如果只写入一个类的实例,这将使输出更长,但如果您编写几个(不同的)实例,则效率会更高。 我不清楚你的例子是否真的使用了一个类,但这是JOS比预期更长的一般原因。
顺便说一句:这是偶然的,但我不认为JSONlogging类名(如你在你的例子),所以它可能不会做你所需要的。
存储less量信息的原因是串行forms相对较大,是因为它存储了有关正在串行化的对象的类别的信息。 如果你存储了你的列表副本,那么你会发现这个文件没有增长太多。 存储相同的对象两次,差异很小。
重要的优点是:相对容易使用,速度相当快,可以进化(就像XML一样)。 但是,这些数据是相当不透明的,它只是Java,将数据紧密地耦合到类,而不可信的数据很容易导致DoS。 你应该考虑序列化的forms,而不是只是把implements Serializable
随处可见。
如果没有太多的数据,可以将对象保存到java.util.Properties对象中。 一个键/值对的例子是user_1234_firstname = Peter。 使用reflection保存和加载对象可以使事情变得更容易。
Java的内置序列化如何工作?
每当我们想要序列化一个对象,我们实现java.io.Serializable接口。 这个接口没有任何方法来实现,即使我们正在实现它来向编译器或JVM (称为标记接口 ) 指示某些东西 。 所以如果JVM看到一个类是可序列化的,它将对这些类执行一些预处理操作。 操作是,它添加了以下两个示例方法。
private void writeObject(java.io.ObjectOutputStream stream) throws IOException { stream.writeObject(name); // object property stream.writeObject(address); // object property } private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { name = (String) stream.readObject(); // object property address = (String) stream.readObject();// object property }
什么时候应该用它来代替其他的持久化技术?
当发送方和接收方都是Java时,内置的Serialization
是有用的。 如果你想避免上述types的问题,我们在框架的帮助下使用XML或JSON。