gpt4 book ai didi

java - JAXB 包装的通用对象的 Setter 方法从未被调用

转载 作者:太空宇宙 更新时间:2023-11-04 13:05:12 24 4
gpt4 key购买 nike

我正在尝试解码名为 Key 的泛型类的 ArrayList。

Key 有 setValue() 方法,该方法接收通用参数。

关键类

@XMLRootElement(name = "Key")
public class Key<T>{

@XMLElement(name = "Key")
public setKey(T value){
this.value = value
}
}

具体ArrayList

@XMLElementWrapper(name = "Keys")
@XMLElement(name = "Key")
public setKeys(ArrayList<Key> keys){
this.keys = keys;
}

XML文件的这部分

<Keys>
<Key>2</Key>
</Keys>

运行代码将创建 ArrayList 并且其中将有一个 Key 对象。但 key 将为空。

(我尝试过调试,发现它没有调用该类的 setKey() setter)

与它的通用性有什么关系吗?提前致谢。

编辑

在过去的一天里,我对此进行了很多调试,现在我可以说,问题在于实例化 ArrayList 后,在 XML 中为每个键标签创建每个键时,解码器使用键的空构造函数,并且从不调用它的 setter ,因此我有一个包含键的 ArrayList,其“值”数据成员为 null

谁能解释一下我做错了什么吗?为什么 setter 没有被调用?

谢谢。

最佳答案

你可能不走运。解码器如何知道 2 是一个整数,而不是一个 double 或 long 或时间戳或其他具有可以将 2 解析为自身的自定义适配器的类。

您想要的注释基本上如下(减去我将在稍后解释的 @XmlJavaTypeAdapter),但如果您尝试在没有适配器的情况下运行该代码,您将得到 NullPointerException,因为 JAXB 无法处理对象上的 @XmlValue 注释(这就是它处理 T 的方式)。 JAXB 无法处理它的原因是它无法知道该对象是什么。

现在,如果您有自己的自定义规则来确定 T 的类型(例如,当来自 XML 时,T 始终为整数,或者如果不包含“.”,则 T 为整数,否则为 Double),那么您可以使用适配器实现您自己的逻辑,这就是我在下面演示的内容(我使用了第二条规则)。

@XmlRootElement(name="root")
public class SO {

private List<Key<?>> keys;

@XmlElementWrapper(name="Keys")
@XmlElement(name="Key")
public void setKeys(List<Key<?>> keys) {
this.keys = keys;
}

public List<Key<?>> getKeys() {
return keys;
}

@XmlType
public static class Key<T> {

private T val;

@XmlValue
@XmlJavaTypeAdapter(ToStringAdapter.class)
public void setKey(T val) {
this.val = val;
}

public String toString() {
return "Key(" + val + ")";
}

}

public static class ToStringAdapter extends XmlAdapter<String, Object> {

@Override
public Object unmarshal(String v) throws Exception {
if(v.contains(".")) {
return Double.parseDouble(v);
} else {
return Integer.parseInt(v);
}
}

@Override
public String marshal(Object v) throws Exception {
return v.toString(); //Will never be called anyway so you could also throw an exception here
}

}

private static final String XML_INT = "<root><Keys><Key>2</Key></Keys></root>";
private static final String XML_DOUBLE = "<root><Keys><Key>2.7</Key></Keys></root>";

public static void main(String [] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Key.class, SO.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
SO so = (SO) unmarshaller.unmarshal(new StringReader(XML_INT));
System.out.print(so.keys);
System.out.println(" " + so.keys.get(0).val.getClass().getSimpleName());
so = (SO) unmarshaller.unmarshal(new StringReader(XML_DOUBLE));
System.out.print(so.keys);
System.out.println(" " + so.keys.get(0).val.getClass().getSimpleName());
}

}

关于java - JAXB 包装的通用对象的 Setter 方法从未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34532456/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com