2010-01-22 6 views
11

Es gibt eine bestimmte Klasse in einer Third-Party-Bibliothek, die ich serialisieren möchte. Wie würde ich das machen?In Java Wie serialisiere ich eine Klasse, die nicht als serialisierbar gekennzeichnet ist?

Ich nehme an, dass ich eine Methode schreiben muss, die ein Objekt der Klasse einnimmt und Reflektion verwendet, um die privaten Elementwerte abzurufen. Dann würde ich zur Deserialisierung Reflektionen verwenden, um die Werte zurückzugeben.

Würde das funktionieren? Gibt es einen leichteren Weg?

+0

benötigen Sie es kompatibel mit zukünftigen Versionen? –

+0

Nein, es muss nicht mit zukünftigen Versionen kompatibel sein. – Kyle

+0

Wollen Sie nur die Daten persistieren? Wenn ja, warum nicht JAXB? – Boltimuss

Antwort

12

Sie könnten einfach ein Übertragungsobjekt verwenden, das Serializable implementiert und dieselben Felder wie das Objekt des Drittanbieters hat. Lassen Sie das Transferobjekt eine Methode implementieren, die ein Objekt der ursprünglichen Dritten Klasse gibt und fertig:

Pseudo-Code:

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); 
} 

Sie müssen nur darauf achten, dass die Mitglieder richtig, wenn Sie serialisiert werden habe irgendwelche speziellen Mitgliedsobjekte bekommen.

Alternativ, wenn die Third-Party-Klasse nicht final ist, können Sie sie erweitern, Serializable implementieren und eigene Methoden writeObject und readObject schreiben.

prüfen für einige Serialisierung Infos:

Serialization Secrets

+0

Danke, das scheint gut, was mache ich mit den privaten Member-Variablen? Gibt es dafür einen einfachen Weg oder brauche ich eine Reflexion? – Kyle

+0

Yep Reflection ist die einzige Möglichkeit, auf nicht sichtbare Felder zuzugreifen. : / – fasseg

2

Sie müssen es in etwas wickeln, die die Serialisierung der Fall ist.

Im Idealfall unterstützt die Drittanbieterklasse eine andere Form der Serialisierung, z. B. XML-Serialisierung (die auf Bean-Eigenschaften basiert). Wenn nicht, müssen Sie Ihre eigenen rollen. Ob das eine Reflexion oder nur Getter, Setter und Konstruktoren beinhaltet, hängt von der Klasse ab.

In jedem Fall würde der Wrapper das Objekt in ein Byte [] oder einen String oder etwas anderes konvertieren und das in die Serialisierungsausgabe schreiben. Bei der Deserialisierung rekonstruiert es das Objekt aus diesen Daten.

Die beiden Methoden, um Ihre Wrapper sind von der Art der Dritten Klasse

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

Viel hängt umzusetzen hat. Ist es endgültig, hat es einen Konstruktor ohne Argumente, kann man es mit bekannten Werten konstruieren oder wird es von einer anderen Klasse konstruiert, enthält es selbst nicht-serialisierbare Mitglieder?

Am einfachsten ist es, die Klasse zu dekompilieren, fügen Sie eine implementiert Serializable, und neu kompilieren, aber wenn es nicht-Serialisierbare Mitglieder enthält, werden die Dinge komplizierter.

0

Eine andere mögliche Lösung kann darin bestehen, eine Reihe von privaten Methoden innerhalb Ihrer Serializable-Klasse zu definieren, die die Instanzen der Third-Party-Klasse verwendet. Diese speziellen Methoden sind Teil eines speziellen Callback-Vertrags, den das Serialisierungssystem anbietet. Diese Methoden werden aufgerufen während des Serialisierungs-/Deserialisierungsprozesses. Die Unterschriften müssen wie:

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. 
} 

Dieses Beispiel verdeutlicht diese Idee weiter:

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; 
    } 


} 

Beachten Sie, dass die thirdPartyInstance in MyClass müssen transiente ansonsten eine Ausnahme vom Typ deklariert werden ‚java.io.NotSerializableException‘ tritt ein. Für weitere Erklärungen siehe: SCJP Sun Certified Programmer für Java 6 von "Cathy Sierra", Seite Nummer 497

Verwandte Themen