若要添加到其他答案中,通过实现 ,可以获得类对象的“自动”序列化功能。无需实现任何其他逻辑,它就可以工作了。Java 运行时将使用反射来弄清楚如何封送和取消封送对象。java.io.Serializable
在早期版本的Java中,反射非常慢,因此序列化大型对象图(例如在客户端 - 服务器RMI应用程序中)是一个性能问题。为了处理这种情况,提供了接口,这就像但是具有自定义编写的机制来执行编组和取消编组功能(您需要在类上实现和方法)。这为您提供了解决反射性能瓶颈的方法。java.io.Externalizable
java.io.Serializable
readExternal
writeExternal
在最新版本的Java(当然是1.3以上)中,反射的性能比以前要好得多,因此这不是一个问题。我怀疑你很难从现代JVM中获得有意义的好处。Externalizable
此外,内置的Java序列化机制不是唯一的一个,您可以获得第三方替换,例如JBoss序列化,它要快得多,并且是默认值的直接替代品。
一个很大的缺点是你必须自己保持这个逻辑 - 如果你添加,删除或更改类中的字段,你必须改变你的/方法来解释它。Externalizable
writeExternal
readExternal
综上所述,是Java的遗物1.1天。真的不再需要它了。Externalizable
序列化提供了用于存储对象并在以后重新创建对象的默认功能。它使用详细格式来定义要存储的对象的整个图形,例如,假设您有一个linkedList,并且您的代码如下所示,那么默认序列化将发现所有链接的对象并将序列化。在默认序列化中,对象完全由其存储的位构造,没有构造函数调用。
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("/Users/Desktop/files/temp.txt"));
oos.writeObject(linkedListHead); //writing head of linked list
oos.close();
但是,如果您希望限制序列化或不希望序列化对象的某些部分,请使用 Externalizable。可外部化接口扩展了可序列化接口,并添加了两个方法: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;
希望它有帮助。如果我犯了任何错误,我很抱歉。谢谢。
-
Java 套接字:程序在套接字处停止。getInputStream() w/o error? “在输入流之前”是 cmd 行上的最后一个生命体征。没有引发异常。为什么会发生这种情况?我不明白。。。 args[0] 是 5000。编辑:冲洗没有帮助。
-
-
如何找出序列化 Java 对象的 serialVersionUID? 我有几个可序列化的类,它们是在没有指定串行VersionUID的情况下编译的。我现在需要向这些类添加一些数据成员,但希望保留一些已经序列化的对象。 是否无论如何都要找出这些序列化对象的
-
为什么Java的序列化比第三方API慢? 在处理套接字并在它们上序列化对象的过程中,我注意到有一些第三方库可以在Java上更快地进行对象序列化,例如。到目前为止,我期望Java的序列化是优化和最快的。因为,它依赖于语言,并
-
java.io.Serializable 类的意义是什么? 在“外行”术语中,我想知道是否有人可以向我解释导入Serializable类以实现java.io.Serializable接口的重要性和一般重要性。来自 Java 学生的提问