下面(在本问题的最后)是一个使用Java泛型的通用JAXB marshaller / unmarshaller。 有用。它可以用一行编组/解组JAXB对象:
JAXBUtils jaxbUtils = new JAXBUtils(ObjectFactory.class);
SomeClass object = jaxbUtils.unmarshall("<some xml >...");
String xml = jaxbUtils.marshall(object);
我还需要克隆其中的一些对象,所以我使用marshall和unmarshall深度克隆任何JAXB对象。 这也可以在没有任何编译器错误的情况下工作(只是通过注释抑制了一些警告)。
SomeClass object = ... some JAXB object obtained from XML
SomeClass cloneObject = clone(object);
但是在另一个环境中(持续集成)我在克隆方法返回行中遇到编译器错误:
type parameters of <T>T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,java.lang.Object
return unmarshal(marshal(object));
^
我将本地环境从1.6.0_27降级到1.6.0_23,因此我在CI服务器中使用了完全相同的版本,因为我发现在这些版本之间修复了与通用代码相关的一些错误:
java版“1.6.0_23” Java(TM)SE运行时环境(版本1.6.0_23-b05)
但代码仍在为我工作,没有编译器错误,单元测试通过,一切正常。
我尝试将克隆方法更改为:
public <T> T clone(T object) throws UnsupportedEncodingException, JAXBException {
return this.<T>unmarshal(this.<T>marshal(object));
}
这也为我编译并看起来因为它给编译器提供了更多提示,但我不确定它是否会解决服务器中的问题,因为我无法重现错误。
您是否发现在克隆方法中使用通用代码有任何问题? 它是编译器中的错误还是我的代码不正确? 如果它不正确,为什么它对我有效!?
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import org.xml.sax.InputSource;
public class JAXBUtils {
private Marshaller marshaller;
private Unmarshaller unmarshaller;
public JAXBUtils(Class... classesToBeBound) throws JAXBException {
final JAXBContext context = JAXBContext.newInstance(classesToBeBound);
unmarshaller = context.createUnmarshaller();
marshaller = context.createMarshaller();
}
@SuppressWarnings("unchecked")
public <T> String marshal(T object) throws UnsupportedEncodingException, JAXBException {
return marshal(object, object.getClass().getSimpleName(), (Class<T>) object.getClass());
}
public <T> String marshal(T object, String name, Class<T> clazz) throws JAXBException {
final JAXBElement<T> jaxbElement = new JAXBElement<T>(new QName(name), clazz, object);
final OutputStream os = new ByteArrayOutputStream();
marshaller.marshal(jaxbElement, os);
return os.toString();
}
@SuppressWarnings("unchecked")
public <T> T unmarshal(String xml) throws UnsupportedEncodingException, JAXBException {
final InputSource is = new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")));
final Object object = unmarshaller.unmarshal(is);
// JAXB sometimes returns directly the object and sometimes wraps it in a JAXBElement.
// Not sure why just handling both cases.
return object instanceof JAXBElement ? ((JAXBElement<T>) object).getValue() : (T) object;
}
public <T> T clone(T object) throws UnsupportedEncodingException, JAXBException {
return unmarshal(marshal(object));
}
}
更新:它给出编译器错误的服务器是RedHat Linux(5或6不确定)。 正如我所说的java版本是一样的,所以我想这个bug是针对windows固定的,而不是针对linux的。 我将尝试访问一些linux机器来尝试。
更新:代码在debian / open-jdk和ubuntu / sun-jdk6u23中编译时没有任何错误或警告。 我无法在RedHat / sun-jdk6u23上进行测试。