在java中,如何序列化未标记为Serializable的类?

我要序列化的第三方库中有一个特定的类。 我该怎么做呢?

我假设我必须编写一个方法来接受类的对象并使用reflection来获取私有成员值。 然后,为了反序列化,我会使用reflection来放回值。

这会有用吗? 有更容易的方法吗?

您可以使用实现Serializable的传输对象,并且具有与第三方对象相同的字段。 让传输对象实现一个方法,该方法返回原始第三方类的对象,并且您已完成:

伪代码:

class Thirdparty{ int field1; int field; } class Transfer implements Serializable{ int field1; int field2; /* Constructor takes the third party object as an argument for copying the field values. For private fields without getters use reflection to get the values */ Transfer (Thirdparty orig){ this.field1=orig.field1; this.field2=orig.field2; } ThirdParty getAsThirdParty(){ Thirdparty copy=new ThirdParty(); copy.field1=this.field1; copy.field2=this.field2; return copy; } /* override these methods for custom serialization */ void writeObject(OutputStream sink); void readObject(InputStream src); } 

如果您有任何特殊的成员对象,您只需确保成员序列化正确。

或者,如果第三方类不是final,你可以只扩展它,让它实现Serializable并编写自己的writeObject和readObject方法。

点击此处查看一些序列化信息:

序列化秘密

您需要将其包装成执行序列化的内容。

理想情况下,第三方类支持其他forms的序列化,例如XML序列化(基于bean属性)。 如果没有,你必须自己动手。 无论是涉及reflection还是仅涉及getter,setter和构造函数都取决于类。

在任何情况下,包装器都会将对象转换为byte []或String或其他内容,并将其写入序列化输出。 在反序列化时,它从该数据重建对象。

您的包装器必须实现的两种方法是

 private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; 

很大程度上取决于第三方课程的性质。 它是最终的,它是否有一个无参数构造函数,你可以根据已知值构造它还是由另一个类构造,它本身是否包含非Serializable成员?

最简单的方法是反编译类,添加一个实现Serializable,并重新编译它,但如果它包含非Serializable成员,事情会变得更复杂。

另一种可能的解决方案可能是在Serializable类中定义一组使用第三方类实例的私有方法。这些特殊方法是序列化系统提供的特殊回调契约的一部分。这些方法将在序列化期间调用/反序列化过程。 他们的签名必须如下:

 private void writeObject(ObjectOutputStream os) { // your code for saving the third party variables } private void readObject(ObjectInputStream is) { // your code to read the third party state, create a new ThirdParty instance, // and assign it to your class. } 

这个例子进一步澄清了这个想法:

 public class MyClass implements Serializable { transient private ThirdParty thirdPartyInstance ; private int myClassVariable ; private void writeObject(ObjectOutputStream oos) { try { oos.defaultWriteObject(); oos.writeInt(thirdPartyInstance.getThirdPartyVariable()); oos.writeInt(thirdPartyInstance.getFourthPartyInstance().getFourthPartyVariable()); } catch(Exception e) { e.printStackTrace(); } } private void readObject(ObjectInputStream ois) { try { ois.defaultReadObject(); //the call to defaultReadObject method must always be before any other code in the try block //Reconstructing thirdPartyInstance thirdPartyInstance =new ThirdParty(ois.readInt(),new FourthParty(ois.readInt())); } catch(Exception e) { e.printStackTrace(); } } MyClass(int myClassVariable, ThirdParty thirdPartyInstance) { this.myClassVariable=myClassVariable; this.thirdPartyInstance=thirdPartyInstance; } ThirdParty getThirdPartyInstance() { return thirdPartyInstance; } int getMyClassVariable() { return myClassVariable; } public static void main(String args[]) { FourthParty fourthPartyInstance=new FourthParty(45); ThirdParty thirdPartyInstance=new ThirdParty(13,fourthPartyInstance); MyClass myClassInstance=new MyClass(7,thirdPartyInstance); System.out.println("Before: ThirdParty variable value is "+myClassInstance.getThirdPartyInstance().getThirdPartyVariable()); System.out.println("Before: FourthParty variable value is "+myClassInstance.getThirdPartyInstance().getFourthPartyInstance().getFourthPartyVariable()); System.out.println("Before: MyClass variable value is "+myClassInstance.getMyClassVariable()); try { FileOutputStream fios=new FileOutputStream("D://TestFileq.ser"); ObjectOutputStream oos=new ObjectOutputStream(fios); oos.writeObject(myClassInstance); oos.close(); FileInputStream fi = new FileInputStream("D://TestFileq.ser"); ObjectInputStream objectIn = new ObjectInputStream(fi); MyClass myClassInst = (MyClass)objectIn.readObject(); System.out.println("After: ThirdParty variable value is "+myClassInst.getThirdPartyInstance().getThirdPartyVariable()); System.out.println("After: FourthParty variable value is "+myClassInst.getThirdPartyInstance().getFourthPartyInstance().getFourthPartyVariable()); System.out.println("After:MyClass variable value is "+myClassInst.getMyClassVariable()); } catch (Exception e) { e.printStackTrace(); } } } class ThirdParty { private int thirdPartyVariable; private FourthParty fourthPartyInstance; ThirdParty(int thirdPartyVariable,FourthParty fourthPartyInstance) { this.thirdPartyVariable=thirdPartyVariable; this.fourthPartyInstance=fourthPartyInstance; } int getThirdPartyVariable() { return thirdPartyVariable; } FourthParty getFourthPartyInstance() { return fourthPartyInstance; } } class FourthParty { private int fourthPartyVariable; FourthParty(int fourthPartyVariable) { this.fourthPartyVariable=fourthPartyVariable; } int getFourthPartyVariable() { return fourthPartyVariable; } } 

请注意,MyClass中的thirdPartyInstance必须声明为transient,否则会发生类型为“java.io.NotSerializableException”的exception。 有关更多说明,请参阅:“Cathy Sierra”的SCJP Sun认证Java 6程序员,第497页