我想序列化第三方庫中有一個特定的類。我會如何去做這件事?在java中,我如何序列化一個沒有標記爲可序列化的類?
我假設我將不得不編寫一個方法,該方法需要一個類的對象並使用反射來獲取私有成員值。然後爲了反序列化,我將使用反射來將值返回。
會這樣嗎?有更容易的方法嗎?
我想序列化第三方庫中有一個特定的類。我會如何去做這件事?在java中,我如何序列化一個沒有標記爲可序列化的類?
我假設我將不得不編寫一個方法,該方法需要一個類的對象並使用反射來獲取私有成員值。然後爲了反序列化,我將使用反射來將值返回。
會這樣嗎?有更容易的方法嗎?
您可以使用實現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方法。
入住這裏有些系列化的相關信息:
你需要將它包裝成的東西做的序列化。
理想情況下,第三方類支持一些其他形式的序列化,例如XML序列化(基於bean屬性)。如果不是,你必須推出自己的。無論是涉及反射還是隻是獲取者,setter和構造函數都依賴於類。
在任何情況下,包裝器都會將對象轉換爲byte []或String或其他東西,並將其寫入序列化輸出中。在反序列化過程中,它從數據中重建對象。
這兩種方法的包裝必須實現的
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
這很大程度上取決於第三方類的性質。它是否是最終的,它是否有一個無參數構造函數,您可以構造給定的已知值,還是由另一個類構造,它本身是否包含非序列化成員?
最簡單的方法是反編譯類,添加一個實現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必須聲明瞬態否則類型的異常「java.io.NotSerializableException」發生。 欲瞭解更多解釋,請參閱: SCJP Java認證程序員,'Cathy Sierra',頁碼497
您是否需要它與w/future版本兼容? – 2010-01-22 01:15:13
不需要,它不需要與將來的版本兼容。 – Kyle 2010-01-22 01:38:49
你只是想要堅持數據?如果是這樣,爲什麼不使用JAXB? – Boltimuss 2010-01-22 03:13:32