2010-01-22 2 views
11

В сторонней библиотеке есть определенный класс, который я хочу сериализовать. Как мне это сделать?В java, как мне сериализовать класс, который не отмечен Serializable?

Я предполагаю, что мне придется написать метод, который принимает объект класса и использует отражение, чтобы получить значения частных членов. Тогда для десериализации я бы использовал отражение, чтобы вернуть значения.

Будет ли это работать? Есть ли более простой способ?

+0

Вам нужна была бы совместимость с будущими версиями? –

+0

Нет, это не обязательно должно быть совместимо с будущими версиями. – Kyle

+0

Вы просто хотите сохранить данные? Если да, почему бы не использовать JAXB? – Boltimuss

ответ

12

Вы можете просто использовать объект передачи, который реализует 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); 
} 

Вы просто должны убедиться, что члены сериализовать правильно, если вы получили специальные объекты-участники.

В качестве альтернативы, если сторонний класс не является окончательным, вы можете просто расширить его, реализовать этот инструмент Serializable и написать собственные методы writeObject и readObject.

Проверить здесь для некоторой сериализации Infos:

Serialization Secrets

+0

Спасибо, это кажется хорошим, что мне делать с частными переменными-членами? Есть ли простой способ для этого или мне нужно отражение? – Kyle

+0

yep reflection - единственный способ получить доступ к невидимым полям. : / – fasseg

2

Вы должны обернуть его в нечто, что делает сериализацию.

В идеале сторонний класс поддерживает некоторую другую сериализацию, например, сериализацию XML (которая основана на свойствах бина). Если нет, вам нужно сворачивать самостоятельно. Включает ли это отражение или просто геттеры, сеттеры и конструкторы зависит от класса.

В любом случае оболочка преобразует объект в байт [] или строку или что-то еще и записывает это в вывод сериализации. При десериализации он восстанавливает объект из этих данных.

Два метода вашей обертка для реализации являются

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

Многое зависит от характера класса третьей стороны. Является ли это окончательным, имеет ли он конструктор без аргументов, вы можете его построить с помощью известных значений или построить другой класс, не содержит ли он сам себя несериализуемых членов?

Самый простой способ - декомпилировать класс, добавить средство Serializable и перекомпилировать его, но если он содержит несериализуемые элементы, все усложняется.

0

Другим возможным решением может быть определение набора частных методов внутри вашего класса 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; 
    } 


} 

Обратите внимание, что thirdPartyInstance в MyClass должны быть объявлены транзиторной иначе исключение типа «java.io.NotSerializableException» имеет место. Для получения дополнительной информации см.: SCJP Sun Certified Programmer для Java 6 от «Cathy Sierra», номер страницы 497

Смежные вопросы