首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的Serializable和Externalizable有什么区别?

Java中的Serializable和Externalizable有什么区别?
EN

Stack Overflow用户
提问于 2009-05-03 19:58:19
回答 11查看 128.5K关注 0票数 294

在Java中,SerializableExternalizable有什么不同?

EN

回答 11

Stack Overflow用户

发布于 2009-05-03 21:51:00

除此之外,通过实现java.io.Serializable,您可以获得类对象的“自动”序列化功能。不需要实现任何其他逻辑,它会正常工作。Java运行时将使用反射来确定如何编组和解组对象。

在Java的早期版本中,反射非常慢,因此序列化大型对象图(例如,在客户端-服务器RMI应用程序中)是一个性能问题。为了处理这种情况,提供了java.io.Externalizable接口,它类似于java.io.Serializable,但具有自定义编写的机制来执行编组和解组功能(您需要在类上实现readExternalwriteExternal方法)。这为您提供了绕过反射性能瓶颈的方法。

在Java的最新版本(当然是1.3以上)中,反射的性能比以前好得多,因此这不是什么大问题。我怀疑您很难从使用现代Externalizable的JVM虚拟机中获得有意义的好处。

此外,内置的Java序列化机制并不是唯一的机制,您还可以获得第三方的替代品,比如JBoss序列化,它的速度要快得多,并且是默认序列化的临时替代品。

Externalizable的一个很大的缺点是您必须自己维护这个逻辑--如果您在类中添加、删除或更改字段,则必须更改您的writeExternal/readExternal方法来解决这个问题。

总之,Externalizable是Java1.1时代的遗物。真的不再需要它了。

票数 282
EN

Stack Overflow用户

发布于 2013-03-20 16:02:49

序列化提供了存储和稍后重新创建对象的默认功能。它使用verbose格式来定义要存储的整个对象图,例如,假设你有一个linkedList,你的代码如下,那么默认的序列化将发现所有链接的对象并进行序列化。在默认序列化中,对象完全由其存储的位构造,没有构造函数调用。

代码语言:javascript
复制
  ObjectOutputStream oos = new ObjectOutputStream(
      new FileOutputStream("/Users/Desktop/files/temp.txt"));
  oos.writeObject(linkedListHead); //writing head of linked list
  oos.close();

但是,如果你想要有限制的序列化,或者不想序列化对象的某一部分,那么就使用Externalizable。Externalizable接口扩展了Serializable接口,并添加了两个方法: writeExternal()和readExternal()。它们会在序列化或反序列化时自动调用。在使用Externalizable时,我们应该记住默认构造函数应该是公共的,否则代码将抛出异常。请遵循以下代码:

代码语言:javascript
复制
public class MyExternalizable implements Externalizable
{

private String userName;
private String passWord;
private Integer roll;

public MyExternalizable()
{
}

public MyExternalizable(String userName, String passWord, Integer roll)
{
    this.userName = userName;
    this.passWord = passWord;
    this.roll = roll;
}

@Override
public void writeExternal(ObjectOutput oo) throws IOException 
{
    oo.writeObject(userName);
    oo.writeObject(roll);
}

@Override
public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException 
{
    userName = (String)oi.readObject();
    roll = (Integer)oi.readObject();
}

public String toString()
{
    StringBuilder b = new StringBuilder();
    b.append("userName: ");
    b.append(userName);
    b.append("  passWord: ");
    b.append(passWord);
    b.append("  roll: ");
    b.append(roll);
   
    return b.toString();
}
public static void main(String[] args)
{
    try
    {
        MyExternalizable m  = new MyExternalizable("nikki", "student001", 20);
        System.out.println(m.toString());
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/Desktop/files/temp1.txt"));
        oos.writeObject(m);
        oos.close();
        
        System.out.println("***********************************************************************");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/Desktop/files/temp1.txt"));
        MyExternalizable mm = (MyExternalizable)ois.readObject();
        mm.toString();
        System.out.println(mm.toString());
    } 
    catch (ClassNotFoundException ex) 
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
    catch(IOException ex)
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
}
}

在这里,如果你注释默认的构造器,那么代码将抛出下面的异常:

代码语言:javascript
复制
 java.io.InvalidClassException: javaserialization.MyExternalizable;     
 javaserialization.MyExternalizable; no valid constructor.

我们可以观察到,由于密码是敏感信息,所以我没有在writeExternal(ObjectOutput oo)方法中序列化它,也没有在readExternal(ObjectInput oi)中设置相同的值。这就是Externalizable提供的灵活性。

上述代码的输出如下所示:

代码语言:javascript
复制
userName: nikki  passWord: student001  roll: 20
***********************************************************************
userName: nikki  passWord: null  roll: 20

我们可以观察到,因为我们没有设置passWord的值,所以它是空的。

通过将密码字段声明为瞬态,也可以实现相同的目的。

代码语言:javascript
复制
private transient String passWord;

希望能有所帮助。如果我犯了任何错误,我向你道歉。谢谢。

票数 39
EN

Stack Overflow用户

发布于 2016-04-08 02:57:27

SerializableExternalizable之间的主要区别

  1. Marker接口Serializable是不带任何方法的标记接口。Externalizable接口包含两个方法:writeExternal()readExternal().
  2. Serialization process:实现Serializable接口的类将启动默认的序列化过程。程序员定义的序列化过程将被踢入实现Externalizable的类,interface.
  3. MaintenanceIncompatible changes可能会中断序列化。
  4. Backward兼容性和控制:如果您必须支持多个版本,则可以通过Externalizable界面进行完全控制。您可以支持对象的不同版本。如果你实现了class
  5. public,你要负责序列化Externalizable super无参数构造函数Serializable使用反射来构造对象,不需要任何参数构造函数。但是Externalizable需要公共的无参数constructor.

有关更多详细信息,请参阅Hitesh Gargblog

票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/817853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档