Java JAXB和继承在封送时起作用;但不是拆封

Java JAXB和继承在封送时起作用;但不是拆封,java,inheritance,jaxb,Java,Inheritance,Jaxb,我想封送/取消封送继承自另一个类的类的对象 我从课程开始: import java.util.List; 公共类事物{ 私有列表字符串; 公共列表getStrings(){ 返回字符串; } 公共无效设置字符串(列表字符串){ this.strings=字符串; } } 我扩展了这个类并用JAXB注释对其进行注释 import java.util.List; 导入javax.xml.bind.annotation.*; @XmlRootElement 公共类JaxbThing扩展了这个东西{

我想封送/取消封送继承自另一个类的类的对象

我从课程
开始:

import java.util.List;
公共类事物{
私有列表字符串;
公共列表getStrings(){
返回字符串;
}
公共无效设置字符串(列表字符串){
this.strings=字符串;
}
}
我扩展了这个类并用JAXB注释对其进行注释

import java.util.List;
导入javax.xml.bind.annotation.*;
@XmlRootElement
公共类JaxbThing扩展了这个东西{
//@xmlementwrapper(name=“list”)
@XmlElementWrapper(name=“strings”)
@xmlement(name=“string”)
公共列表getStrings(){
返回super.getStrings();
}
公共无效设置字符串(列表字符串){
超级设置字符串(字符串);
}
}
然后运行以下编组/解编组程序:

导入java.io.File;
导入java.util.array;
导入javax.xml.bind.*;
公共班机{
公共静态void main(字符串[]args){
JaxbThing t=新的JaxbThing();
t、 集合字符串(数组.asList(“a”、“b”、“c”));
试一试{
文件f=新文件(“jaxb File.xml”);
JAXBContext context=JAXBContext.newInstance(JaxbThing.class);
Marshaller m=context.createMarshaller();
m、 元帅(t,f);
Unmarshaller um=context.createUnmarshaller();
JaxbThing t2=(JaxbThing)um.unmarshal(f);
System.out.println(t2.getStrings());//我希望看到[a,b,c]
}捕获(JAXBEException e){
e、 printStackTrace();
}
}
}
XML文件的内容是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbThing>
    <strings>
        <string>a</string>
        <string>b</string>
        <string>c</string>
    </strings>
</jaxbThing>
当我期待看到
[a,b,c]

如果我以这种方式注释
字符串
属性:

@xmlementwrapper(name=“list”)
//@xmlementwrapper(name=“strings”)
@xmlement(name=“string”)
公共列表getStrings(){
返回super.getStrings();
}
然后控制台显示预期的
[a、b、c]

我猜JAXB解组器使用class
Thing
而不是
JaxbThing
来解组XML文件内容。事实上,如果我用
@xmltransive
注释类
东西
,我会得到预期的结果

但是,我不理解JAXB的这种行为


谁能给我解释一下吗?提前感谢。

问题在于您正在重写父类中的属性。JAXB认为
JAXBThing
has“

  • 一个名为
    strings
    (继承自
    String
    )的属性映射到元素
    strings
  • 名为
    strings
    (在
    JAXBThing
    上定义)的属性映射到元素
    strings
    下的元素
    string
  • 如果在
    JAXBThing
    上的
    setStrings
    方法中放置一个断点,您将看到它首先使用正确的数据调用,然后使用覆盖初始集的错误数据调用第二次(因为它认为它们是共享一个setter的不同属性)

    通过使用
    @xmltransive
    对类进行注释,始终可以删除
    对象

    import java.util.List;
    import javax.xml.bind.annotation.XmlTransient;
    
    @XmlTransient
    public class Thing {
      private List<String> strings;
    
      public List<String> getStrings() {
        return strings;
      }
    
      public void setStrings(List<String> strings) {
          System.out.println("Thing" + strings);
        this.strings = strings;
      }
    
    }
    
    import java.util.List;
    导入javax.xml.bind.annotation.XmlTransient;
    @XmlTransient
    公共类事物{
    私有列表字符串;
    公共列表getStrings(){
    返回字符串;
    }
    公共无效设置字符串(列表字符串){
    System.out.println(“Thing”+字符串);
    this.strings=字符串;
    }
    }
    
    了解更多信息


      • 非常感谢您的回答。我已经按照您的建议做了。您是对的,
        setStrings
        方法被调用了两次。但是,至少在我的实验中,它从来没有用正确的值调用过

        下面我提供了修改后的示例代码。我添加了几行来跟踪执行。我还激活了marshaller格式的输出,以便更好地查看解组过程中发生的情况

        基类
        东西

        import java.util.List;
        公共类事物{
        私有列表字符串;
        公共列表getStrings(){
        返回字符串;
        }
        公共无效设置字符串(列表字符串){
        /*new*/System.out.printf(“Thing.setStrings called.Prev.this.strings:%s(大小%s)。收到的strings参数:%s”,this.strings,(this.strings!=null?this.strings.size():“null”),strings);
        this.strings=字符串;
        /*new*/System.out.printf(“.new this.strings:%s(大小%s)。%n%n”,this.strings,(this.strings!=null?this.strings.size():“null”);
        }
        }
        
        扩展类
        JaxbThing

        import java.util.List;
        导入javax.xml.bind.annotation.*;
        @XmlRootElement
        公共类JaxbThing扩展了这个东西{
        //@xmlementwrapper(name=“list”)
        @XmlElementWrapper(name=“strings”)
        @xmlement(name=“string”)
        公共列表getStrings(){
        返回super.getStrings();
        }
        公共无效设置字符串(列表字符串){
        /*new*/System.out.printf(“调用了JaxbThing.setStrings.Received strings参数:%s(大小%s)%n”),string,(string!=null?string.size():“null”);
        超级设置字符串(字符串);
        }
        }
        
        测试程序:

        结果如下(我已将行编号):

        在解组期间,将构建一个新的
        JaxbThing
        ,首先使用0长度的字符串列表(第7行)调用其
        JaxbThing.setStrings
        。因此,将调用
        Thing.setStrings
        (第8行)。对象字符串字段的先前值(
        this.strings
        )为null。然后,再次调用
        JaxbThing.setString
        (第10行),但现在使用了一个字符串列表,其中包含一个带“\n”字符的字符串加上4个空格(我猜这对应于XML文件的缩进)。两条注释:

      • JaxbThing.setStrings
        从未使用正确的值调用过(除非我没有看到它)
      • JaxbThing.setString的第二次调用
        
        import java.util.List;
        import javax.xml.bind.annotation.XmlTransient;
        
        @XmlTransient
        public class Thing {
          private List<String> strings;
        
          public List<String> getStrings() {
            return strings;
          }
        
          public void setStrings(List<String> strings) {
              System.out.println("Thing" + strings);
            this.strings = strings;
          }
        
        }
        
        import java.io.File;
        import java.util.Arrays;
        import javax.xml.bind.*;
        
        public class Main {
          public static void main(String[] args) {    
            System.out.println("---- Initiallizing");
            JaxbThing t = new JaxbThing();
            t.setStrings(Arrays.asList("a", "b", "c"));
            try {
              File f = new File("jaxb-file.xml");
        
              JAXBContext context = JAXBContext.newInstance(JaxbThing.class);
        
              System.out.println("---- Marshalling");
              Marshaller m = context.createMarshaller();
              m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);   /*new*/
              m.marshal(t, f);
        
              System.out.println("---- UnMarshalling");
              Unmarshaller um = context.createUnmarshaller();
              JaxbThing t2 = (JaxbThing) um.unmarshal(f);
        
              System.out.println("---- Showing results");
              System.out.println(t2.getStrings());  // I expect to see [a, b, c]
        
            } catch (JAXBException e) {
              e.printStackTrace();
            }
          }
        }
        
        1  ---- Initiallizing
        2  JaxbThing.setStrings called. Received strings param: [a, b, c] (size 3)
        3  Thing.setStrings called. Prev. this.strings: null (size null). Received strings param: [a, b, c]. New this.strings: [a, b, c] (size 3).
        4  
        5  ---- Marshalling
        6  ---- UnMarshalling
        7  JaxbThing.setStrings called. Received strings param: [] (size 0)
        8  Thing.setStrings called. Prev. this.strings: null (size null). Received strings param: []. New this.strings: [] (size 0).
        9  
        10 JaxbThing.setStrings called. Received strings param: [
               ] (size 1)
        11 Thing.setStrings called. Prev. this.strings: [
               ] (size 1). Received strings param: [
               ]. New this.strings: [
               ] (size 1).
        12 
        13 ---- Showing results
        14 [
                 ]