[英]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.