2011-12-23 46 views
1

我對XMLEncoder有以下問題。我想序列化類,看起來像這樣:僅限XML序列化序列化一個字段

public class MyClass{ 
    private Object myObject; 
    private Object anotherObject; 
    private static MyClass instance = new MyClass(); 

    [myObject and anotherObject are set in the class later...] 

    public static MyClass getInstance(){ 
     return instance; 
    } 

    [getter and setter methods here] 
} 

現在我想序列化這樣的對象(內部MyClass的):

public void saveObject(){ 
     [try catch stuff not shown] 
     FileOutputStream fos = new FileOutputStream(new File("object.xml")); 
    XMLEncoder xmle = new XMLEncoder(fos); 
    xmle.writeObject(instance); 
    xmle.close(); 
} 

但我object.xml不包含的價值觀myObject和anotherInstance,看起來像這樣:

<?xml version="1.0" encoding="UTF-8"?> 
<java version="1.6.0_24" class="java.beans.XMLDecoder"> 
<object class="MyClass"/> 
</java> 

這是怎麼回事? XMLEncoder是否檢測到具有相同類的靜態字段的循環並且不會進一步序列化它?但我沒有得到任何錯誤... 我可以標記該字段爲不可序列化或其他?

回答

1

如果你想在任何類上使用XmlEncoder(不遵守JavaBeans約定的類),這裏有一個有用的鏈接。

Advanced use of XmlEncoder

編輯:書中有一個小Blurb的,可能是對你有所幫助。

XMLEncoder通過克隆對象圖並記錄創建克隆所需的步驟來工作。通過這種方式,XMLEncoder具有對象圖的「工作副本」,它模仿XMLDecoder解碼文件所需的步驟。通過監視此工作副本的狀態,編碼器可以省略將屬性值設置爲其默認值的操作,從而生成具有很少冗餘信息的簡潔文檔。

所以,在你的榜樣,如果myObjectanotherObject值是在instance變量設置,而不是被初始化爲默認情況下,一切正常。

public void saveObject(){ 
     [try catch stuff not shown] 
     instance.setObject(new Object()); 
     FileOutputStream fos = new FileOutputStream(new File("object.xml")); 
    XMLEncoder xmle = new XMLEncoder(fos); 
    xmle.writeObject(instance); 
    xmle.close(); 
} 
+0

嗯,它不是我第一次使用XMLEncoder,它的工作原理總是和你描述的一樣......但是在這種情況下,它不工作!即使我把所有的init東西放在構造函數裏面...... – reox 2011-12-23 15:16:23

2

XMLEncoder編碼'Java Beans'。它沒有意識到田野;它只使用getters和setter。如果有'循環',那麼它將使用xml:idxml:idref來處理參考。

+0

是的,我有我的getters和setters,但方法不知何故被使用? – reox 2011-12-24 11:07:32

+1

@reox所以你要求我們調試你沒有包含在OP中的代碼,而不是你所做的代碼? – 2011-12-24 20:20:14

1

XMLEncoder被設計用於JavaBeans。這意味着,在系列化樹所有對象必須:

  • 有一個公共的默認(即無參)構造

  • 有一個getter和你想序列的每個屬性的設置(一用於序列化的getter和用於反序列化的setter)。

作爲一個側面說明,如果你想保持的getter/setter但不想序列化的屬性,事情就與使用內省的稍微複雜些:

// let's get the BeanInfo of class MyClass 
BeanInfo info = Introspector.getBeanInfo(MyClass.class); 

// we'll work with PropertyDescriptors to prevent the bar attribute from being serialized 
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors(); 
for (PropertyDescriptor descriptor : propertyDescriptors) { 
    if (descriptor.getName().equals("bar")) { 
     //the correct PropertyDescriptor is set to transient. 
     //Note that you actually have to do this via the BeanInfo/PropertyDescriptor for it to work 
     descriptor.setValue("transient", Boolean.TRUE); 
    } 
} 
+0

同意。一個特別常見的問題是當試圖編碼一個對象A時,該對象包含一個沒有公共默認(無參數)構造函數的對象B作爲成員。在這種情況下,B將不會顯示在編碼版本中。 – hrabinowitz 2014-05-30 17:15:44