[英]Casting objects via reflection in Java
我正在编写一个反序列化方法,如下所示:
public <T> T deserialize(Object[] result, String[] fields, Class<T> type);
因此,基本上,我将传入一个包含所有对象的数据结果数组和一个类类型T,该类需要将数组中的数据转换为给定类中的类型,并创建一个新的类型T并返回它。 String[]
字段是与Object[]
结果中的数据相对应的字段名称。 字段名称将对应于T
类。
转换将需要使用给定类的反射来找出每个字段的类型。
例如。
result = ["Mike", "London", 28];
fields = ["name", "location", "age" ];
T类=
public class GivenClass{
private String name;
private String location;
private Integer age;
public GivenClass(String name, String location, Integer age){
this.name = name;
this.location = location;
this.age = age;
}
}
static class GivenClass {
private String name;
private String location;
private Integer age;
public GivenClass(String name, String location, Integer age) {
this.name = name;
this.location = location;
this.age = age;
}
public GivenClass(Map<String, Object> data) throws Exception {
for (Field f : GivenClass.class.getDeclaredFields())
f.set(this, data.get(f.getName()));
}
public Map<String, Object> serialize() throws Exception {
Map<String, Object> fields = new HashMap<String, Object>();
for (Field f : GivenClass.class.getDeclaredFields())
fields.put(f.getName(), f.get(this));
return fields;
}
@Override
public String toString() {
return "age=" + age + ", location=" + location + ", name=" + name;
}
}
public static void main(String[] args) throws Exception {
GivenClass o1 = new GivenClass("Mike", "London", 28);
Map<String, Object> serialized = o1.serialize();
GivenClass o2 = new GivenClass(serialized);
System.out.println(o2.toString());
}
输出:
age=28, location=London, name=Mike
您需要自己进行转换。 反射不会转换(它只会检查对象的类型是否正确)
反射不会为您提供方法/构造函数参数的名称。 (您可以从调试字节码中获取它们,但这确实很痛苦)
我采用的方法是使用约定,即构造函数参数与字段的顺序相同。 您还将要假设构造函数参数的类型与字段类型匹配。 ;)
只要有可能,我也会使用原语而不是包装器。 使用int
除非您希望null
为有效选项。 在这种情况下,您应该考虑如何表示。 对于文本,我通常根据上下文使用空字符串或空白字段表示null
或NaN
。
这样做的问题是,在Java中,它无法获取构造函数的参数名称。
对于此特定示例,您将需要一个默认构造函数,您可以使用该构造函数创建一个空对象。
public GivenClass() {
super();
}
然后,您可以使用反射来获取类的字段,然后为其设置适当的值。
但是我认为注释构造函数,然后在deserialize
方法中获取注释信息会容易得多。 在这种情况下,您不需要获取字段并创建一个空的构造函数。
例:
您需要创建一个这样的注释:
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Property
{
String value();
}
然后可以像下面这样在构造函数中使用它:
public GivenClass(@Property("name") String name, @Property("location") String location, @Property("age") Integer age) {
// ...
}
正如彼得·劳里(Peter Lawrey)所说,强制转换不会将字符串转换为整数。
如果您的bean遵循标准的bean约定(即您具有getter和setters),则可以使用BeanUtils 。 BeanUtils进行一些标准转换,您可以通过添加Converter来添加更多转换 。
请参见以下示例:
import org.apache.commons.beanutils.BeanUtils;
public class BeanUtilsTest {
public static class Obj {
private int number;
private String string;
public void setNumber(int number) {
this.number = number;
}
public void setString(String string) {
this.string = string;
}
public String toString() {
return "number=" + number + " string=" + string;
}
}
public static void main(String args[]) throws Exception {
String[] values = new String[] { "1", "two" };
String[] properties = new String[] { "number", "string" };
Obj obj = new Obj();
for (int i = 0; i < properties.length; i++) {
BeanUtils.setProperty(obj, properties[i], values[i]);
}
System.out.println("obj=" + obj);
}
}
这产生作为输出:
obj=number=1 string=two
请注意,以上示例仅具有二传手,但仍然有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.