在Java中,Serializable和Externalizable有什么不同?
发布于 2009-05-03 21:51:00
除此之外,通过实现java.io.Serializable,您可以获得类对象的“自动”序列化功能。不需要实现任何其他逻辑,它会正常工作。Java运行时将使用反射来确定如何编组和解组对象。
在Java的早期版本中,反射非常慢,因此序列化大型对象图(例如,在客户端-服务器RMI应用程序中)是一个性能问题。为了处理这种情况,提供了java.io.Externalizable接口,它类似于java.io.Serializable,但具有自定义编写的机制来执行编组和解组功能(您需要在类上实现readExternal和writeExternal方法)。这为您提供了绕过反射性能瓶颈的方法。
在Java的最新版本(当然是1.3以上)中,反射的性能比以前好得多,因此这不是什么大问题。我怀疑您很难从使用现代Externalizable的JVM虚拟机中获得有意义的好处。
此外,内置的Java序列化机制并不是唯一的机制,您还可以获得第三方的替代品,比如JBoss序列化,它的速度要快得多,并且是默认序列化的临时替代品。
Externalizable的一个很大的缺点是您必须自己维护这个逻辑--如果您在类中添加、删除或更改字段,则必须更改您的writeExternal/readExternal方法来解决这个问题。
总之,Externalizable是Java1.1时代的遗物。真的不再需要它了。
发布于 2013-03-20 16:02:49
序列化提供了存储和稍后重新创建对象的默认功能。它使用verbose格式来定义要存储的整个对象图,例如,假设你有一个linkedList,你的代码如下,那么默认的序列化将发现所有链接的对象并进行序列化。在默认序列化中,对象完全由其存储的位构造,没有构造函数调用。
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时,我们应该记住默认构造函数应该是公共的,否则代码将抛出异常。请遵循以下代码:
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);
}
}
}在这里,如果你注释默认的构造器,那么代码将抛出下面的异常:
java.io.InvalidClassException: javaserialization.MyExternalizable;
javaserialization.MyExternalizable; no valid constructor.我们可以观察到,由于密码是敏感信息,所以我没有在writeExternal(ObjectOutput oo)方法中序列化它,也没有在readExternal(ObjectInput oi)中设置相同的值。这就是Externalizable提供的灵活性。
上述代码的输出如下所示:
userName: nikki passWord: student001 roll: 20
***********************************************************************
userName: nikki passWord: null roll: 20我们可以观察到,因为我们没有设置passWord的值,所以它是空的。
通过将密码字段声明为瞬态,也可以实现相同的目的。
private transient String passWord;希望能有所帮助。如果我犯了任何错误,我向你道歉。谢谢。
发布于 2016-04-08 02:57:27
Serializable和Externalizable之间的主要区别
Serializable是不带任何方法的标记接口。Externalizable接口包含两个方法:writeExternal()和readExternal().Serializable接口的类将启动默认的序列化过程。程序员定义的序列化过程将被踢入实现Externalizable的类,interface.Externalizable界面进行完全控制。您可以支持对象的不同版本。如果你实现了classExternalizable super无参数构造函数:Serializable使用反射来构造对象,不需要任何参数构造函数。但是Externalizable需要公共的无参数constructor.有关更多详细信息,请参阅Hitesh Garg的blog。
https://stackoverflow.com/questions/817853
复制相似问题