用于克隆JAXB对象的java泛型代码中的编译器错误

时间:2013-09-05 20:32:32

标签: java generics jaxb

下面(在本问题的最后)是一个使用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上进行测试。

0 个答案:

没有答案