簡體   English   中英

通過反射在Java中投射對象

[英]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為有效選項。 在這種情況下,您應該考慮如何表示。 對於文本,我通常根據上下文使用空字符串或空白字段表示nullNaN

這樣做的問題是,在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM