gpt4 book ai didi

使用 Objenesis 创建静态内部类实例时出现 java.lang.InstantiationError

转载 作者:行者123 更新时间:2023-12-02 01:19:34 26 4
gpt4 key购买 nike

我正在尝试创建一个实用方法,该方法应该能够深度克隆任何对象。(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 具有 1 的引用,则不会陷入无限循环。我还使用了一个 Map 来检查是否完全相等 (==),而不是使用 equals()
  • 创建了一个自定义异常类,该异常类只会被传递,而不是在每个级别上抛出新的异常(导致巨大的深度引起的异常)。

最佳答案

我终于明白了。您的代码不处理数组。因此实例化“[Ljava.util.concurrent.ConcurrentHashMap$Node;”失败这是一个节点数组。

但是,我确实主张您不应该这样做。您最终会得到相当复杂的代码。根据您想要执行的操作,您可以使用 Jackson 或 XStream 进行编码/解码来执行复制。

如果您确实想继续该路径,则在 clone 方法的 null 检查之后将需要类似的内容。

    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;
}

关于使用 Objenesis 创建静态内部类实例时出现 java.lang.InstantiationError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57960950/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com