2011-12-23 56 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