Я пытаюсь объединить несколько вхождений одного подкласса ChildListElement универсального суперкласса ParentListElement в список, используя JAXB.Проблема заключается в том, что JAXB отменяет вызов суперкласса вместо подкласса.Как заставить JAXB отменять вызов ChildListElement вместо ParentListElement без блокировки одного подкласса ChildListElement?
Спасибо за ваше время и помощь.: -)
Это файлы / классы:
main.java
ParentChildTests.java
ParentChildFactory.java
childBucket.xml
ParentBucket.java
ChildBucket.java
ParentListElement.java
ChildListElement.java
Использование аннотаций оболочки и элементов в ParentBucket работает, только если указано type=ChildListElement.class
.Но это противоречит цели иметь общий суперкласс, потому что один подкласс ChildListElement заблокирован. Я хочу иметь возможность иметь несколько подклассов ParentListElement.Каждый список будет содержать только один вид подкласса за один раз.
Работает - отменяет маршалинг для ChildListElement, НО ЗАМКАЕТ НА ОДНОЙ ПОДКЛАСС:
@XmlElementWrapper( name = "elements" )
@XmlElements( { @XmlElement( name="element", type=ChildListElement.class ) } )
Не работает - отменяет маршалинг для ParentListElement:
@XmlElementWrapper( name = "elements" )
@XmlElements( { @XmlElement( name="element" ) } )
main.java:
import GenListVsJaxbTests.ParentChildTests;
import javax.xml.bind.JAXBException;
public class Main
{
public static void main(String[] args) throws JAXBException
{
ParentChildTests.testChildBucket();
ParentChildTests.testChildBucketFromXml();
}
}
ParentChildTests.java:
package GenListVsJaxbTests;
import javax.xml.bind.JAXBException;
public class ParentChildTests
{
public static void testChildBucket()
{
ChildBucket bucket = ParentChildFactory.getNewChildBucket();
bucket.test();
}
public static void testChildBucketFromXml() throws JAXBException
{
ChildBucket bucket = ParentChildFactory.loadNewChildBucketFromXml ( "src/GenListVsJaxbTests/ChildBucket.xml" );
bucket.test();
}
}
ParentChildFactory.java:
package GenListVsJaxbTests;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ParentChildFactory
{
private static int MAX_ELEMENTS = 3;
public static ChildBucket getNewChildBucket()
{
ChildBucket childBucket = new ChildBucket();
List<ChildListElement> list = new ArrayList<>();
for ( int i = 0; i < MAX_ELEMENTS; i ++ )
{
ChildListElement el = new ChildListElement();
el.setParentListElMember ( String.valueOf ( i ) );
el.setChildListElMember ( String.valueOf ( i + 10 ) );
list.add ( el );
}
childBucket.setElementList ( list );
return childBucket;
}
public static ChildBucket loadNewChildBucketFromXml ( String fileName ) throws JAXBException
{
File inFile = new File( fileName );
JAXBContext jaxbContext = JAXBContext.newInstance ( ChildBucket.class );
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ChildBucket bucket = (ChildBucket) jaxbUnmarshaller.unmarshal(inFile);
return bucket;
}
}
childBucket.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<childBucket
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation='ChildBucket.xsd'
>
<childBucketMember>child bucket</childBucketMember>
<parentBucketMember>parent bucket</parentBucketMember>
<elements>
<element>
<childListElMember>child element 1</childListElMember>
<parentListElMember>parent element 1</parentListElMember>
</element>
<element>
<childListElMember>child element 2</childListElMember>
<parentListElMember>parent element 2</parentListElMember>
</element>
<element>
<childListElMember>child element 3</childListElMember>
<parentListElMember>parent element 3</parentListElMember>
</element>
<element>
<childListElMember>child element 4</childListElMember>
<parentListElMember>parent element 4</parentListElMember>
</element>
</elements>
</childBucket>
ParentBucket.java:
package GenListVsJaxbTests;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import java.util.List;
public class ParentBucket<LE extends ParentListElement>
{
protected String parentBucketMember = "parentBucketMember";
List<LE> elementList;
public String getParentBucketMember()
{
return parentBucketMember;
}
public void setParentBucketMember(String parentBucketMember)
{
this.parentBucketMember = parentBucketMember;
}
public List<LE> getElementList()
{
return elementList;
}
@XmlElementWrapper( name = "elements" )
@XmlElements( { @XmlElement( name="element" ) } )
// @XmlElements( { @XmlElement( name="element", type=ChildListElement.class ) } )
public void setElementList(List<LE> elementList)
{
this.elementList = elementList;
}
public void test()
{
System.out.println("ParentBucket.test");
System.out.println("parentBucketMember: " + parentBucketMember);
for ( LE el : elementList )
{
el.test();
}
}
}
ChildBucket.java:
package GenListVsJaxbTests;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ChildBucket extends ParentBucket<ChildListElement>
{
protected String childBucketMember = "childBucketMember";
public String getChildBucketMember()
{
return childBucketMember;
}
public void setChildBucketMember(String childBucketMember)
{
this.childBucketMember = childBucketMember;
}
public void test()
{
System.out.println("ChildBucket.test");
System.out.println("childBucketMember: " + childBucketMember);
super.test();
System.out.println("---");
for ( ChildListElement el : elementList )
{
el.test();
}
System.out.println("===");
}
}
ParentListElement.java:
package GenListVsJaxbTests;
public class ParentListElement
{
protected String parentListElMember = "parentListElMember";
public String getParentListElMember()
{
return parentListElMember;
}
public void setParentListElMember(String parentListElMember)
{
this.parentListElMember = parentListElMember;
}
public void test()
{
System.out.println("ParentListElement.test");
System.out.println("parentListElMember: " + parentListElMember);
}
}
ChildListElement.java:
package GenListVsJaxbTests;
public class ChildListElement extends ParentListElement
{
protected String childListElMember = "childListElMember";
public String getChildListElMember()
{
return childListElMember;
}
public void setChildListElMember(String childListElMember)
{
this.childListElMember = childListElMember;
}
@Override
public void test()
{
super.test();
System.out.println("ChildListElement.test");
System.out.println("childListElMember: " + childListElMember);
}
}
Последовательность для цикла выдает эту ошибку во время выполнения (сокращенно):
ClassCastException: ParentListElement cannot be cast to ChildListElement
При правильной сортировке вывод выглядит следующим образом:
"C:\Program Files\Java\jdk1.8.0_211\bin\java" -Didea.launcher.port=7538 "-Didea.launcher.bin.path=[SNIP] com.intellij.rt.execution.application.AppMain Main
ChildBucket.test
childBucketMember: childBucketMember
ParentBucket.test
parentBucketMember: parentBucketMember
ParentListElement.test
parentListElMember: 0
ChildListElement.test
childListElMember: 10
ParentListElement.test
parentListElMember: 1
ChildListElement.test
childListElMember: 11
ParentListElement.test
parentListElMember: 2
ChildListElement.test
childListElMember: 12
---
ParentListElement.test
parentListElMember: 0
ChildListElement.test
childListElMember: 10
ParentListElement.test
parentListElMember: 1
ChildListElement.test
childListElMember: 11
ParentListElement.test
parentListElMember: 2
ChildListElement.test
childListElMember: 12
===
ChildBucket.test
childBucketMember: child bucket
ParentBucket.test
parentBucketMember: parent bucket
ParentListElement.test
parentListElMember: parent element 1
ChildListElement.test
childListElMember: child element 1
ParentListElement.test
parentListElMember: parent element 2
ChildListElement.test
childListElMember: child element 2
ParentListElement.test
parentListElMember: parent element 3
ChildListElement.test
childListElMember: child element 3
ParentListElement.test
parentListElMember: parent element 4
ChildListElement.test
childListElMember: child element 4
---
ParentListElement.test
parentListElMember: parent element 1
ChildListElement.test
childListElMember: child element 1
ParentListElement.test
parentListElMember: parent element 2
ChildListElement.test
childListElMember: child element 2
ParentListElement.test
parentListElMember: parent element 3
ChildListElement.test
childListElMember: child element 3
ParentListElement.test
parentListElMember: parent element 4
ChildListElement.test
childListElMember: child element 4
===
Process finished with exit code 0
При неправильной сортировке вывод выглядит так:
"C:\Program Files\Java\jdk1.8.0_211\bin\java" -Didea.launcher.port=7542 "-Didea.launcher.bin.path=[SNIP] com.intellij.rt.execution.application.AppMain Main
ChildBucket.test
childBucketMember: childBucketMember
ParentBucket.test
parentBucketMember: parentBucketMember
ParentListElement.test
parentListElMember: 0
ChildListElement.test
childListElMember: 10
ParentListElement.test
parentListElMember: 1
ChildListElement.test
childListElMember: 11
ParentListElement.test
parentListElMember: 2
ChildListElement.test
childListElMember: 12
---
ParentListElement.test
parentListElMember: 0
ChildListElement.test
childListElMember: 10
ParentListElement.test
parentListElMember: 1
ChildListElement.test
childListElMember: 11
ParentListElement.test
parentListElMember: 2
ChildListElement.test
childListElMember: 12
===
ChildBucket.test
childBucketMember: child bucket
ParentBucket.test
parentBucketMember: parent bucket
ParentListElement.test
parentListElMember: parent element 1
ParentListElement.test
parentListElMember: parent element 2
ParentListElement.test
parentListElMember: parent element 3
ParentListElement.test
parentListElMember: parent element 4
---
Exception in thread "main" java.lang.ClassCastException: GenListVsJaxbTests.ParentListElement cannot be cast to GenListVsJaxbTests.ChildListElement
at GenListVsJaxbTests.ChildBucket.test(ChildBucket.java:27)
at GenListVsJaxbTests.ParentChildTests.testChildBucketFromXml(ParentChildTests.java:17)
at com.caci.irma.experiment.Main.main(Main.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Process finished with exit code 1