为什么JAXB需要一个无参数构造器来进行编组?

如果您尝试编组引用不具有无参数构造函数的复杂types的类,例如:

import java.sql.Date; @XmlRootElement(name = "Foo") @XmlAccessorType(XmlAccessType.FIELD) public class Foo { int i; Date d; //java.sql.Date does not have a no-arg constructor } 

与Java的一部分JAXB实现,如下所示:

  Foo foo = new Foo(); JAXBContext jc = JAXBContext.newInstance(Foo.class); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Marshaller marshaller = jc.createMarshaller(); marshaller.marshal(foo, baos); 

JAXB将抛出一个

 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions java.sql.Date does not have a no-arg default constructor 

现在,我明白了为什么JAXB需要解组的无参构造函数 – 因为它需要实例化对象。 但为什么JAXB在编组时需要一个无参的构造函数呢?

此外,另一个尼特,为什么Java的JAXB实现会抛出一个exception,如果该字段为空,并且不打算编组?

我是否错过了某些东西,或者这些在Java的JAXB实现中只是错误的实现select?

JAXB(JSR-222)实现初始化其元数据时,它确保它可以同时支持编组和解组。

对于没有无参数构造函数的POJO类,可以使用types级别的XmlAdapter来处理它:

java.sql.Date默认不支持(尽pipe在EclipseLink JAXB(MOXy)中是这样的)。 这也可以使用在字段,属性或包级别通过XmlAdapter指定的XmlAdapter进行处理:


此外,另一个尼特,为什么Java的JAXB实现会抛出一个exception,如果该字段为空,并且不打算编组?

你看到什么exception? 通常情况下,当一个字段为空时,它不包含在XML结果中,除非用@XmlElement(nillable=true)注释,在这种情况下,元素将包含xsi:nil="true"


UPDATE

你可以做到以下几点:

SqlDateAdapter

下面是一个XmlAdapter ,它将从您的JAXB实现不知道如何处理的java.sql.Date转换为XmlAdapter执行的java.util.Date

 package forum9268074; import javax.xml.bind.annotation.adapters.*; public class SqlDateAdapter extends XmlAdapter<java.util.Date, java.sql.Date> { @Override public java.util.Date marshal(java.sql.Date sqlDate) throws Exception { if(null == sqlDate) { return null; } return new java.util.Date(sqlDate.getTime()); } @Override public java.sql.Date unmarshal(java.util.Date utilDate) throws Exception { if(null == utilDate) { return null; } return new java.sql.Date(utilDate.getTime()); } } 

XmlAdapter是通过@XmlJavaTypeAdapter注解注册的:

 package forum9268074; import java.sql.Date; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name = "Foo") @XmlAccessorType(XmlAccessType.FIELD) public class Foo { int i; @XmlJavaTypeAdapter(SqlDateAdapter.class) Date d; //java.sql.Date does not have a no-arg constructor } 

您似乎觉得JAXB自检代码将具有用于初始化的特定操作path。 如果是这样,那将导致很多重复的代码,并且会是一个糟糕的实现。 我会想象,JAXB代码有一个共同的例程,第一次检查一个模型类是需要的,并validation它遵循所有必要的约定。 在这种情况下,它是失败的,因为其中一个成员没有所需的无参数构造函数。 初始化逻辑很可能不是特定的编组/parsing器,也不太可能将当前的对象实例考虑在内。

一些企业和dependency injection框架使用reflectionClass.newInstance()来创build类的新实例。 这个方法需要一个公共的无参数构造函数来实例化对象。