Java 不使用默认POJO构造函数将POJO转换为XML

Java 不使用默认POJO构造函数将POJO转换为XML,java,xml,javabeans,default-constructor,Java,Xml,Javabeans,Default Constructor,我正在尝试使用Java.beans.xmlcoder将POJO(普通旧Java对象)转换为XML。我的代码工作得很好,但我发现了一个有趣的问题,即当我在POJO中省略默认构造函数时出现的问题。课程如下 没有默认构造函数的POJO public class NFLTeam implements Serializable { private String name; private String description; // public NFLTeam() { // //

我正在尝试使用Java.beans.xmlcoder将POJO(普通旧Java对象)转换为XML。我的代码工作得很好,但我发现了一个有趣的问题,即当我在POJO中省略默认构造函数时出现的问题。课程如下

没有默认构造函数的POJO

public class NFLTeam implements Serializable {

  private String name;
  private String description;

  // public NFLTeam() {
  //
  // }

  public NFLTeam(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getName() {
        return name;
    }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

}
public static void main(String args[]) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream);
    NFLTeam team = new NFLTeam("Bears", "Play for Chicago");
    xmlEncoder.writeObject(team);
    xmlEncoder.close();
    System.out.println(byteArrayOutputStream);
}
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
<object class="oce.wsd.pojos.NFLTeam">
    <void property="description">
      <string>Play for Chicago</string>
    </void>
    <void property="name">
     <string>Bears</string>
   </void>
</object>
</java>
调用XMLEncoder

public class NFLTeam implements Serializable {

  private String name;
  private String description;

  // public NFLTeam() {
  //
  // }

  public NFLTeam(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getName() {
        return name;
    }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

}
public static void main(String args[]) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream);
    NFLTeam team = new NFLTeam("Bears", "Play for Chicago");
    xmlEncoder.writeObject(team);
    xmlEncoder.close();
    System.out.println(byteArrayOutputStream);
}
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
<object class="oce.wsd.pojos.NFLTeam">
    <void property="description">
      <string>Play for Chicago</string>
    </void>
    <void property="name">
     <string>Bears</string>
   </void>
</object>
</java>
省略默认构造函数的控制台输出

java.lang.InstantiationException: oce.wsd.pojos.NFLTeam
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement XMLEncoder.writeObject(NFLTeam);
Continuing ...
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
</java>
java.lang.InstanceionException:oce.wsd.pojos.NFLTeam
持续的。。。
java.lang.Exception:XMLEncoder:丢弃语句XMLEncoder.writeObject(NFLTeam);
持续的。。。
带有默认构造函数的控制台输出

public class NFLTeam implements Serializable {

  private String name;
  private String description;

  // public NFLTeam() {
  //
  // }

  public NFLTeam(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getName() {
        return name;
    }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

}
public static void main(String args[]) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream);
    NFLTeam team = new NFLTeam("Bears", "Play for Chicago");
    xmlEncoder.writeObject(team);
    xmlEncoder.close();
    System.out.println(byteArrayOutputStream);
}
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
<object class="oce.wsd.pojos.NFLTeam">
    <void property="description">
      <string>Play for Chicago</string>
    </void>
    <void property="name">
     <string>Bears</string>
   </void>
</object>
</java>

为芝加哥队比赛
熊
我在谷歌上搜索,但找不到任何解释。为什么隐式默认构造函数对于XMLEncoder不够?

来自:

如果类不包含构造函数声明,则默认 没有形式参数且没有throws子句的构造函数是 隐式声明

换句话说,如果没有其他n-arg构造函数,则空构造函数是隐式的。你自己试试吧:

public class Main {

    public Main(int i) {

    }

    public static void main(String[] args) {
        new Main(); // error: the constructor Main() is undefined
    }

}
如果不能,XMLEncoder也不能。不幸的是,JAXB(和链接技术)需要非参数构造函数(隐式默认构造函数也可以)

根据规范,对于本机Oracle JAX库,封送和取消封送都需要它

根据人类逻辑,封送/序列化不需要它。例如,最流行的JSON库Jackson只对反序列化有这样的要求

还有第三方XML JAX兼容解析器,它们的限制性也比较小。。。但这个问题通常不是与第三方库斗争的原因

JAX允许使用非公共的非参数构造函数。我通常按如下方式创建:

/** For JAXB only. Do not call directly and do not delete! */
@Deprecated
protected NFLTeam () {
    // nothing
}

我找到了我一直在寻找的答案。“XMLEncoder类是ObjectOutputStream的补充替代品,可用于生成JavaBean的文本表示。”JavaBean是这里的关键。为了使发布的示例中的NFLTeam bean被视为JavaBean,它需要前面提到的默认构造函数。“该类必须有一个公共默认构造函数(不带参数)。这允许在编辑和激活框架内轻松实例化。”

我理解这一点,但我不想用默认构造函数实例化新对象。我已经构建了对象并将其传递给XMLEncoder。我猜XMLEncoder的编码方式需要一个显式的默认构造函数,我认为Java不能区分显式和隐式的n-arg构造函数。在字节码级别上,它必须看起来完全相同……我喜欢你放在里面的Javadoc。我将遵循同样的方法前进!