在Java中迭代成员变量
我有几种情况,其中一个类由任意(但固定)数量的不同类型的变量组成,并且希望迭代这些变量,并在代码中使用它们的名称。有没有比在每个函数中重新键入每个变量名更聪明的方法 我最初的想法是使用HashMap来存储局部变量,但这似乎效率低下,而且不能处理多种类型 模拟以下代码以缩短所需的读数,但其变量通常超过3个:在Java中迭代成员变量,java,oop,variables,iterator,hashmap,Java,Oop,Variables,Iterator,Hashmap,我有几种情况,其中一个类由任意(但固定)数量的不同类型的变量组成,并且希望迭代这些变量,并在代码中使用它们的名称。有没有比在每个函数中重新键入每个变量名更聪明的方法 我最初的想法是使用HashMap来存储局部变量,但这似乎效率低下,而且不能处理多种类型 模拟以下代码以缩短所需的读数,但其变量通常超过3个: class Widget implements Parcelable { String name, code; Long price; public void wri
class Widget implements Parcelable {
String name, code;
Long price;
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(code);
dest.writeLong(price);
}
public Widget(Parcel o) {
name = o.name;
code = o.code;
price = o.price;
}
public String getXML() {
return "<Widget><name>"+name+"</name><code>"+code
+"</code><price>"+price+"</price></Widget>";
}
}
相反,我更喜欢做(伪代码):
如果有许多类的代码遵循相同的模式,我将编写一个代码生成器,从某种定义文件生成Java源代码。然后,您可以让生成器创建与第一个示例类似的简单代码,这比使用通用映射或反射等更容易阅读和理解。定义文件将成为每种对象字段的“官方”源 由于您已经熟悉Python,您的定义文件可以直接构建到Python脚本中以创建源代码。例如:
Objects = {
"Widget": [
(TYPE_STRING, "name"),
(TYPE_STRING, "code"),
(TYPE_LONG, "price"),
],
# ...
}
通过对
类型\u字符串
等的适当定义,编写一些代码从中生成Java源代码应该很简单。通常通过反射解决:
for (Field f : getClass().getDeclaredFields()) {
String name = f.getName();
String value = f.get(this);
}
但是,对于XML的写入/读取,您可能希望使用而不是重新发明轮子 使用Jackson:
序列化与JSON序列化非常相似:只需更改ObjectMapper实例即可使用:
// Important: create XmlMapper; it will use proper factories, workarounds
ObjectMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValue(new Simple());
和POJO一样:
public class Simple {
public int x = 1;
public int y = 2;
}
你会得到如下结果:
<Simple>
<x>1</x>
<y>2</y>
</Simple>
1.
2.
(除非默认情况下输出不缩进:可以使用标准Jackson机制启用缩进)
从XML反序列化POJO
与序列化类似,反序列化与JSON反序列化没有太大区别:
ObjectMapper xmlMapper = new XmlMapper();
Simple value = xmlMapper
.readValue("<Simple><x>1</x><y>2</y></Simple>", Simple.class);
ObjectMapper xmlMapper=new xmlMapper();
简单值=xmlMapper
.readValue(“12”,简单类);
另外,您还可以使用反射,并使用Class.getDeclaredFields()
通过所有声明的字段进行迭代。但根据我的经验,很少有人需要这样做。有很多第三方开源库用于不同的目的,通常使用它们是更好的解决方案(例如,在这个特殊情况下使用Jackson)我认为这是最简单的框架。参考答案,你会有一个想法
它只需创建一个映射类,例如带有所有成员属性和对象可能嵌套的小部件
,然后调用:
XStream xstream = new XStream(new DomDriver());
String xml = xstream.toXML(widgetObject); // <-- Get XML String from object
Widget widget = (Widget)xstream.fromXML(xml); //<-- Get object from XML
XStream XStream=newxstream(newdomdriver());
字符串xml=xstream.toXML(widgetObject);//理想情况下,如果你的类中有这么多的变量,你应该移动ValueObject中的相关变量,并在类中使用它的引用。因为你正在访问成员变量(而不是像你原来的标题那样的局部变量),你可以使用反射来访问它们。有关更多详细信息,请查看反射API和教程。或者,您可以将这些值重构为另一个类,并使用继承或组合来重用代码。您根本不必处理手工构建XML的问题。@EugeneRetunsky:为什么是Jackson而不是JAXB?@HovercraftFullOfEels这是我个人的偏好。依我看,它使用起来更简单。而且它的应用也很广泛。XML我故意把它写成一个字符串,以避免特定的API,并给出任何我可以快速键入的示例。+1虽然我花了一些时间阅读Java反射,但看起来几乎完美。。。虽然这可能需要一些时间来正确地吸收。我可以用这个方法管理大多数情况,其中我在一个对象中列出了许多变量,但到目前为止从SQLite游标填充的情况除外。没有通用的Cursor.getObject(…)可以为f.set(…)强制转换;也许还有另一个问题是必要的。呃,为了映射数据库行,我想让您看看……w.r.t。JPA,这个问题是一般性的,但对我来说,实现是特定于Android的,尽管看起来很有趣。这不是简单地从变量中提取XML,而是在多个类函数中反复迭代局部变量。我喜欢这是一种黑客行为,但感觉像是一种黑客行为。我怀疑@meriton所建议的反思最符合我的目的。如果我找到了一个好的解决方案,我保证会发布一个有效的例子。
ObjectMapper xmlMapper = new XmlMapper();
Simple value = xmlMapper
.readValue("<Simple><x>1</x><y>2</y></Simple>", Simple.class);
XStream xstream = new XStream(new DomDriver());
String xml = xstream.toXML(widgetObject); // <-- Get XML String from object
Widget widget = (Widget)xstream.fromXML(xml); //<-- Get object from XML