簡體   English   中英

使用Objenesis創建靜態內部類的實例時出現java.lang.InstantiationError

[英]java.lang.InstantiationError when creating instance of static inner class with Objenesis

我正在嘗試創建一個實用程序方法,該方法應該能夠深克隆任何對象。 Object.clone()僅在實現Cloneable對象上起作用,我聽說它還是有缺陷的。)

我正在使用Objenesis來創建對象的新實例,而無需使用構造函數。

但是,當嘗試克隆JFrame時,出現以下異常:
(使用該類,因為我認為這應該是一個很好且復雜的測試)

java.lang.InstantiationError: [Ljava.util.concurrent.ConcurrentHashMap$Node;
    at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)

我對任何解決方案持開放態度,不一定僅限於Objenesis。

我的代碼:

private static ObjenesisStd OBJENESIS = new ObjenesisStd();

@SuppressWarnings("unchecked")
public static <T> T clone(T object, boolean deep){
    if(object == null){
        return null;
    }else{
        try {
            T clone = (T) OBJENESIS.newInstance(object.getClass());
            List<Field> fields = ReflectionUtil.getAllFieldsInHierarchy(object.getClass());
            for(Field field : fields){
                boolean isAccessible = field.isAccessible();
                boolean isFinal = ReflectionUtil.isFinal(field);
                field.setAccessible(true);
                ReflectionUtil.setFinal(field, false);
                Class<?> type = field.getType();
                if(!deep || type.isPrimitive() || type == String.class){
                    field.set(clone, field.get(object));
                }else{
                    field.set(clone, clone(field.get(object), true));
                }
                field.setAccessible(isAccessible);
                ReflectionUtil.setFinal(field, isFinal);
            }
            return clone;
        } catch (Throwable e) {
            e.printStackTrace();
            //throw new RuntimeException("Failed to clone object of type " + object.getClass(), e);
            return null;
        }
    }
}


public static void main(String[] args) {
    GetterSetterAccess access = new GetterSetterAccess(JFrame.class);
    JFrame frame = new JFrame("Test Frame");
    for(String attr : access.getAttributes()){
        System.out.println(attr + " " + access.getValue(frame, attr));
    }

    System.out.println("----------------------------------------------");
    frame = clone(frame, true);


    for(String attr : access.getAttributes()){
        System.out.println(attr + " " + access.getValue(frame, attr));
    }
}

編輯:得到了它與接受的答案和一些其他修復一起使用:

  • 避免克隆原始類型的包裝器( Integer.class等)
  • 避免克隆類( Class.class類的對象)
  • 將克隆的對象存儲在Map中並重用它們,因此,如果對象A引用對象B,對象B引用對象A,則不會陷入無限循環。 我還使用了一個檢查完全相等( == )的Map,而不是使用equals()
  • 創建了一個自定義的異常類,該類將被傳遞,而不是在每個級別上引發新的異常(導致大量的由深度引起的)。

我終於弄明白了。 您的代碼無法處理數組。 因此,由於實例化“ [Ljava.util.concurrent.ConcurrentHashMap $ Node;”而失敗。 這是一個節點數組。

但是,我會主張,實際上,您不應該這樣做。 您將得到相當復雜的代碼。 根據您要執行的操作,可以使用Jackson或XStream進行編組/解組來執行復制。

如果您確實想繼續該路徑,則在對clone方法進行空檢查之后,您將需要類似這樣的內容。

    if(object.getClass().isArray()) {
        int length = Array.getLength(object);
        Object array = Array.newInstance(object.getClass().getComponentType(), length);
        for (int i = 0; i < length; i++) {
            Array.set(array, i, clone(Array.get(object, i), true));
        }
        return (T) array;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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