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

在java中,如何序列化未标记为可序列化的类?,java,reflection,serialization,Java,Reflection,Serialization,在第三方库中有一个特定的类,我想序列化它。我该怎么做呢 我假设我必须编写一个方法,该方法接收类的一个对象,并使用反射来获取私有成员值。然后对于反序列化,我将使用反射将值放回原处 这样行吗?有没有更简单的方法 您可以只使用实现Serializable且与第三方对象具有相同字段的传输对象。让transfer对象实现一个返回原始第三方类的对象的方法,您就完成了: 伪代码: class ThirdParty{ int field1; int field2; } class Trans

在第三方库中有一个特定的类,我想序列化它。我该怎么做呢

我假设我必须编写一个方法,该方法接收类的一个对象,并使用反射来获取私有成员值。然后对于反序列化,我将使用反射将值放回原处


这样行吗?有没有更简单的方法

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

伪代码:

class ThirdParty{

    int field1;
    int field2;
}

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,您可以扩展它,让它实现可序列化,并编写您自己的writeObject和readObject方法

检查此处以获取一些序列化信息:


您需要将其包装成能够实现序列化的内容

理想情况下,第三方类支持其他形式的序列化,例如XML序列化(基于bean属性)。如果没有,你必须自己滚。这是涉及反射还是只涉及getter、setter和构造函数取决于类

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

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

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

很大程度上取决于第三方阶级的性质。它是最终的,它是否有一个无参数构造函数,是否可以在给定已知值的情况下构造它,还是由另一个类构造,它本身是否包含不可序列化的成员


最简单的方法是反编译类,添加一个可序列化的实现,然后重新编译它,但如果它包含不可序列化的成员,事情变得更加复杂。

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

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中的第三个PartyInstance必须声明为transient,否则将发生“java.io.NotSerializableException”类型的异常。 有关更多说明,请参阅:
SCJP Sun认证的Java 6程序员,由Cathy Sierra编写,第497页

您需要它与未来版本兼容吗?不需要,它不需要与未来版本兼容。您只是想保留数据吗?如果是这样,为什么不使用JAXB呢?谢谢,这看起来不错,我该如何处理私有成员变量?有没有简单的方法,或者我需要反射?是的,反射是我所知道的访问不可见字段的唯一方法/“序列化机密”链接是新链接:,