说我想用xml表示算术表达式,所以我有:
@XmlRootElement
@XmlTransient
@XmlSeeAlso({Num.class, Add.class})
public abstract class Evaluable
{
public abstract int eval();
}
@XmlRootElement
@XmlType(name = "num")
public class Num extends Evaluable
{
@XmlValue
private int val;
@Override
public int eval()
{
return val;
}
}
@XmlRootElement
@XmlType
public class Add extends Evaluable
{
@XmlAnyElement
private ArrayList<Evaluable> elems;
@Override
public int eval()
{
int sum = 0;
for (Evaluable elem : elems)
{
sum += elem.eval();
}
return sum;
}
}
和我的测试用例:
public class RecursiveUnmarshalTest
{
@Test
public void testAdd() throws Exception
{
String xml = "<add><num>10</num><num>20</num></add>";
assertEquals(30,
((Evaluable) JAXBContext.newInstance(Evaluable.class).createUnmarshaller().unmarshal(new StringReader(
xml))).eval());
}
}
这里的问题是非Evaluable
存储在ArrayList
Add
中,原因是类型擦除,JAXB不知道哪种类型的元素应该反映到,因此Add
的eval中会出现一个强制转换错误。
我测试了这一点:
public class Add extends Evaluable
{
@XmlElements({
@XmlElement(name = "num", type = Num.class),
@XmlElement(name = "add", type = Add.class)
})
private ArrayList<Evaluable> elems;
...
这将被修复。
但我不想在世界各地传播这张桌子。如果我想附加一些子类型,事情就会变得混乱。
所以我的问题是哪种注释适合我的情况?或任何输入unmarshaller的系统?
我正在使用glassfish的JAXB,我无法选择使用。
答案 0 :(得分:1)
您可以使用@XmlElementRef
来获取您要查找的行为:
@XmlElementRef
private ArrayList<Evaluable> elems;
它表示可以使用Evaluable或其任何子类 上下文
啊,这是正确的,因为你将Evaluable
标记为@XmlTransient
,JAXB忽略它并且不认为它存在。您可能已添加它,因为当您没有它时,您会收到以下异常。
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "class forum27826242.Evaluable" or any of its subclasses are not known to this context.
this problem is related to the following location:
at private java.util.ArrayList forum27826242.Add.elems
at forum27826242.Add
at @javax.xml.bind.annotation.XmlSeeAlso(value=[class forum27826242.Num, class forum27826242.Add])
at forum27826242.Num