我需要解析XML文件并使用反射从ArrayList
创建一堆对象。
我用Class.forName()
实现了这个目标。
这是我的代码:
public ArrayList<Sweets> parse(String fileName) throws Exception {
File file = new File(fileName);
Document doc = builder.parse(file);
ArrayList<Sweets> items = new ArrayList<Sweets>();
int itemCount = Integer.parseInt(path
.evaluate("count(/gift/item)", doc));
for (int i = 1; i <= itemCount; i++) {
double sugar = Double.parseDouble(path.evaluate("/gift/item[" + i + "]/@sugar", doc));
String name = path.evaluate("/gift/item[" + i + "]/name", doc);
double weight = Double.parseDouble(path.evaluate("/gift/item[" + i
+ "]/weight", doc));
Class cl = Class.forName("com.epam.lab.model.chocolate." + name);
items.add((Sweets) cl.getConstructor(double.class, double.class)
.newInstance(sugar, weight));
}
return items;
}
它有效,但在这一行:
Class cl = Class.forName("com.epam.lab.model.chocolate." + name);
但是一些缺点是这个方法需要包含类包的全名。
完全取自不同的包装。但我需要从其他地方学习其他课程。 forName()
的限制不允许我这样做。
如何规避Class.forName()
约束?
答案 0 :(得分:3)
有一个很好的替代方法可以将XML读取和解析为Java对象:带注释的JAXB。
阅读:
MyDoc doc = load(MyDoc.class, "/mydoc.xml");
private <T> T load(Class<T> klazz, String xmlResource) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(klazz);
return klazz.cast(jaxbContext.createUnmarshaller()
.unmarshal(getClass().getResourceAsStream(xmlResource)));
} catch (JAXBException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE,
"Cannot read resource " + xmlResource, e);
throw new IllegalStateException(e);
}
}
@XmlRootElement(name="document")
public class MyDoc {
@XmlElement(name="sweetsList")
public List<Sweets> sweets= new ArrayList<>();
}
<document>
<sweetsList>
...
</sweetsList>
</document>
对于其他类,@XmlElement
和@XmlAttribute
使用相同的注释。
答案 1 :(得分:0)
我担心这是不可能的 - 要实例化你需要提供该类的完全限定名称。
但也许你可以在解析的xml中提供更多信息 - 例如包装名称的一部分,不同类型的糖果?
String name = path.evaluate("/gift/item[" + i + "]/name", doc);
String type = path.evaluate("/gift/item[" + i + "]/type", doc);
double weight = Double.parseDouble(path.evaluate("/gift/item[" + i + "]/weight", doc));
Class cl = Class.forName("com.epam.lab.model" + type + "." + name);
或者如果XML格式是密封的,那么也许您可以在特定糖果名称和代表它们的classess包之间创建映射?