序列化和反序列化以及将内部写入文件然后读取它们并在构造函数中传递它们之间的区别

时间:2010-06-28 10:45:34

标签: java serialization

让我们说我们有一个班级

Class A implements serializable{

    String s;
    int i;
    Date d;

    public A(){
    }

    public A(String s, int i, Date d){
        this.s =s;
       blah blah
    }
}

现在让我们说一种方法,我将s,i,d的所有内部值存储到一个文件中并再次读取它们,然后将它们传递给构造函数并创建一个新对象。其次,我序列化然后反序列化为一个新对象。这两种方法之间的基本区别是什么。

我知道序列化将是缓慢而安全的,而另一种方法则不然。任何其他差异。

5 个答案:

答案 0 :(得分:5)

阅读这篇文章,解释了什么是序列化(它适用于Java RMI,但序列化解释和问题是相同的):http://oreilly.com/catalog/javarmi/chapter/ch10.html

我看到的主要区别是:

  • (正如其他答案所说),您有责任序列化 - 反序列化。当其中一个属性是另一个大型复杂类时会发生什么?那你打算做什么?还要保存它的价值吗?
  • 序列化依赖于反射,而文件依赖于getter / setters / constructors。使用反射,您不需要公共setter / getter或带参数的构造函数。有了文件,你需要它们。

从上面的链接中提取:

使用序列化

序列化是内核Java库中的一种机制,用于将对象图写入数据流。然后可以以编程方式操纵该数据流,并且可以通过反转该过程来创建对象的深层副本。这种逆转通常被称为反序列化

特别是序列化有三个主要用途:

  • 作为持久性机制。如果正在使用的流是FileOutputStream,则数据将自动写入文件。
  • 作为复制机制。如果正在使用的流是ByteArrayOutputStream,则数据将被写入内存中的字节数组。然后可以使用此字节数组创建原始对象的副本。
  • 作为沟通机制。如果正在使用的流来自套接字,那么数据将自动通过网络发送到接收套接字,此时另一个程序将决定该做什么。

需要注意的重要一点是序列化的使用与序列化算法本身无关。如果我们有一个可序列化的类,我们可以通过改变我们使用序列化机制输出的方式将它保存到文件或复制它。

答案 1 :(得分:2)

在您的第一种方法中,负责维护数据值之间的逻辑关系(在存储数据的意义上,然后将其读回并构造对象回来了。)

在第二种方法中,Java会在幕后为您完成此任务。

答案 2 :(得分:1)

Java中的序列化和反序列化

序列化是一个过程,通过它我们可以将对象的状态存储到任何存储介质中。我们可以将对象的状态存储到文件中,存储到数据库表等中。反序列化是序列化的相反过程,我们从存储介质中检索对象。

Eg1:假设你有一个Java bean对象,它的变量有一些值。现在,您希望将此对象存储到文件或数据库表中。这可以使用序列化来实现。现在,您可以在需要时随时从文件或数据库中再次检索此对象。这可以通过反序列化来实现:(由Bobin Goswami发布)。

答案 3 :(得分:0)

除了实现自定义序列化方案之外,没有真正的区别,因此通常会涉及更多代码,因为默认情况下序列化只需要一个接口声明。

您可以使用Externalizable实现非常类似的东西 - 您可以精确控制保存的数据,因此您可以选择仅保存构造函数参数并从中构造对象。 (您也可以通过将非构造函数参数标记为瞬态来实现序列化。)

答案 4 :(得分:0)

Joshua Bloch的Effective Java,第2版中的序列化部分。对这个问题真的很好看。要记住一些非常重要的事情:

  1. 使用您自己的自己开发的持久性方法是一种内部语言。从存储中读取数据时,可以控制对象状态的恢复方式。通常这是构造函数和/或静态工厂。保留对象状态的不变量。保持封装是因为您不一定需要将实现细节作为自定义存储的一部分进行公开。当然,缺点是数据经常需要放置,而@pakore很好地概述了序列化有用的情况。

  2. 序列化是一种语言外部机制。 Bloch提出了令人信服的论据,为什么应该最谨慎地调用序列化(特别是Serializiable接口)。序列化可以绕过构造函数,因为对象的重构不依赖于构造函数。存在深刻的安全问题。对象状态的不变量很容易受到攻击。此外,使用Serializable往往会锁定您支持特定的类实现(即,它会破坏封装),因为一旦它变为Serializable,您的大部分对象的状态就会成为类的导出API的一部分(这可以通过将某些实例字段标记为可以主动延迟瞬态)。

  3. TL; DR:序列化是现代基于Java的计算的常见甚至基本方面。这些天的数据必须到位,序列化提供了一种常用的通信机制。由于序列化可能会调用的漏洞,并且因为它可能会使您的对象的内部状态的大部分(或全部)成为其导出的API的一部分,因此应该非常小心地使用Serializable接口。