亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java - 使用反射遞歸修改對象值

Java - 使用反射遞歸修改對象值

慕容森 2022-07-06 10:03:42
我想轉換 Object 的每個 String 屬性(以及它的嵌套對象),我正在使用以下遞歸方法通過反射 API 來實現:    public static void reflect(Object obj) {        if (obj == null) {            return;        }        Class klazz = obj.getClass();        if (klazz.isPrimitive()                || obj instanceof Integer                || obj instanceof Double                || obj instanceof Boolean)            return;        else {            try {                for (Field field : klazz.getDeclaredFields()) {                    field.setAccessible(true);                    Object f = field.get(obj);                    if(f instanceof String) {                        f = transform(f);                        field.set(obj, f);                    }                    else {                        reflect(f);                    }                }            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (IllegalArgumentException e) {                e.printStackTrace();            }        }    }    private static Object transform(Object f) {        f = f + "blabla";        return f;    }@Data@Builderpublic class PrintObject {    private String field1;    private String field2;    private String field3;    private NestedObject field4;}@Data@Builderpublic class NestedObject {    private String field1;    private String field2;    private Integer field3;}NestedObject nestedObject = NestedObject                .builder()                .field1("test")                .field2("test2")                .field3(1)                .build();PrintObject printObject = PrintObject      .builder()      .field1("test")      .field2("Test")      .field3("test")      .field4(nestedObject)      .build();Utils.reflect(printObject);到目前為止,一切正常,如果我執行此操作,那么所有字符串值最后都會附加“blabla”。如果 PrintObject 具有其他數據結構(如 List 或 Map),則會出現問題。例如,如果 PrintObject 類中有另一個字段:private List<String> field5;
查看完整描述

1 回答

?
慕慕森

TA貢獻1856條經驗 獲得超17個贊

ArrayList包含一個long serialVersionUID幫助序列化的字段。當您獲得該值時,它會返回一個 boxed Long。調用getDeclaredFieldsonLong返回一個包含字段的數組,該字段Long.MIN_VALUE是Long. 這就是無限循環的來源。


Long為了解決它,我會像你一樣添加特殊情況處理Integer。您還應該考慮所有其他盒裝原語,例如Float和Byte。


集合將由引用彼此鏈接的結構LinkedList或數組支持。對于鏈接結構,代碼將遍歷它們。要支持數組支持的收集,您需要確定哪些字段是數組并遍歷它們。


字段的類型,通過Field.getType獲得。數組可以通過Class.isArray來識別。不同類型的數組有不同的類型,它們不像 Java 泛型那樣是非具體化的??梢詫⒎窃贾档臄到M強制轉換Object[]為在這種情況下很有用,但它不是類型安全的。可以使用Class.getComponentType來獲取數組中對象的類型。


需要像下面這樣的東西來遞歸數組的條目。


final Class<?> fieldType = field.getType();

if (fieldType.isArray() && !fieldType.getComponentType().isPrimitive()) {

    Object[] fs = (Object[]) f;

    for (Object fi : fs) {

        reflect(fi);

    }

}

另一個問題是可能導致進一步的循環引用StackOverflowException。如果將一個列表作為其自身的成員添加,它將無限遞歸。有必要跟蹤以前訪問過的對象,而不是兩次訪問它們。理想情況下,這將使用 an IdentityHashMap,因為您關心對象的實例而不是它們的相等性。


查看完整回答
反對 回復 2022-07-06
  • 1 回答
  • 0 關注
  • 284 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號