[英]java.lang.InstantiationError when creating instance of static inner class with Objenesis
I am trying to create a utility method that should be able to deep-clone any object. 我正在尝试创建一个实用程序方法,该方法应该能够深克隆任何对象。 ( Object.clone()
only works on Object implementing Cloneable
and I heard it's flawed anyways.) ( Object.clone()
仅在实现Cloneable
对象上起作用,我听说它还是有缺陷的。)
I am using Objenesis to create new instances of objects without the use of constructors. 我正在使用Objenesis来创建对象的新实例,而无需使用构造函数。
However, when trying to clone a JFrame I get the following Exception: 但是,当尝试克隆JFrame时,出现以下异常:
(using this class because I think it should be a good and complex test) (使用该类,因为我认为这应该是一个很好且复杂的测试)
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)
I am open to any solution, not necessarily limited to Objenesis. 我对任何解决方案持开放态度,不一定仅限于Objenesis。
My Code: 我的代码:
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));
}
}
EDIT: Got it to work with the accepted answer and a few more fixes: 编辑:得到了它与接受的答案和一些其他修复一起使用:
Integer.class
etc.) 避免克隆原始类型的包装器( Integer.class
等) Class.class
) 避免克隆类( Class.class
类的对象) ==
) instead of using equals()
. 我还使用了一个检查完全相等( ==
)的Map,而不是使用equals()
。 I finally figured it out. 我终于弄明白了。 Your code doesn't handle arrays. 您的代码无法处理数组。 So it fails with instantiating "[Ljava.util.concurrent.ConcurrentHashMap$Node;" 因此,由于实例化“ [Ljava.util.concurrent.ConcurrentHashMap $ Node;”而失败。 which is an array of Nodes. 这是一个节点数组。
However, I will advocate that indeed, you should not do that. 但是,我会主张,实际上,您不应该这样做。 You will end up with fairly complicated code. 您将得到相当复杂的代码。 Depending on what you want to do, you could use Jackson or XStream to do a marshall / unmarshall to perform the copy. 根据您要执行的操作,可以使用Jackson或XStream进行编组/解组来执行复制。
If you really want to continue that path, you will need something like this after the null check of your clone
method. 如果您确实想继续该路径,则在对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.