深度复制使用反射 Java

huangapple go评论75阅读模式
英文:

deep copy using reflection java

问题

我无法使用反射从类字段获取容器。我尝试了下面的方法,但出现了异常:

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at java.util.Collections.addAll(Collections.java:5455)
public static void copy(Object from, Object to) throws NoSuchFieldException, IllegalAccessException {
    Class<?> fromClass = from.getClass();
    Class<?> toClass = to.getClass();
    Field[] sourceFields = fromClass.getDeclaredFields();
    for (Field fromField : sourceFields) {
        Field toField = toClass.getDeclaredField(fromField.getName());
        toField.setAccessible(true);
        fromField.setAccessible(true);
        if (fromField.getType().equals(toField.getType())) {
            if (!(fromField.getType() == String.class || fromField.getType().isPrimitive())) {
                if (fromField.getType().isAssignableFrom(List.class)) {
                    List list = (List) fromField.get(from);
                    List list1 = (List) toField.get(to);
                    Collections.addAll(list1, list);
                    toField.set(to, fromField.get(from));
                } else if (fromField.getType().isAssignableFrom(Set.class)) {
                    Set set = (Set) fromField.get(from);
                    Set set1 = (Set) toField.get(to);
                    set1.clear();
                    set1.addAll(set);
                    toField.set(to, fromField.get(from));
                }
            } else {
                toField.set(to, fromField.get(from));
            }
        }
    }
}

我不想使用序列化的复制方法,我对反射感兴趣。

英文:

I can't get a container from the class field using reflection. I tried the method below, but got an exception:

Exception in thread &quot;main&quot; java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at java.util.Collections.addAll(Collections.java:5455)
public static void copy(Object from, Object to) throws NoSuchFieldException, IllegalAccessException {
Class&lt;?&gt; fromClass = from.getClass();
Class&lt;?&gt; toClass = to.getClass();
Field[] sourceFields = fromClass.getDeclaredFields();
for (Field fromField : sourceFields) {
Field toField = toClass.getDeclaredField(fromField.getName());
toField.setAccessible(true);
fromField.setAccessible(true);
if (fromField.getType().equals(toField.getType())) {
if (!(fromField.getType() == String.class || fromField.getType().isPrimitive())) {
if (fromField.getType().isAssignableFrom(List.class)) {
List list = (List) fromField.get(from);
List list1 = (List) toField.get(to);
Collections.addAll(list1,list);
toField.set(to, fromField.get(from));
} else if (fromField.getType().isAssignableFrom(Set.class)) {
Set set = (Set) fromField.get(from);
Set set1 = (Set) toField.get(to);
set1.clear();
set.addAll(set1);
toField.set(to, fromField.get(from));
}
} else {
toField.set(to, fromField.get(from));
}
}
}
}

I don't want to use methods of copying via serialization, I'm interested in reflection.

答案1

得分: 1

你这么做是为了训练吗?如果不是,那么请使用一些开源库,这比你想象的要困难得多 - 查看这个链接

你的问题在于你正在向to列表添加内容,而to列表是一个不支持添加操作的实现(顺便说一句,你忽略了结果)。我建议创建一个新的列表并重新赋值,而不是向现有列表添加内容。

List list = (List) fromField.get(from);
List list1 = (List) toField.get(to);
List newList = new ArrayList();
if(list != null)
  Collections.addAll(newList,list);
if(list1 != null)
  Collections.addAll(newList,list1);
toField.set(to, newList);

对于Set,情况类似 - 你当前的Set代码毫无意义,它操作的是Class对象。

英文:

You are doing this for training I hope? If not then use some opensource library, it's a lot harder than you think - check this.

Your problem is that you are adding to the to list, and the to list is an implementation that does not support adding (btw then you are ignoring the result). I suggest creating a new list and reassiging it, instead of adding to the existing one.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-java -->

List list = (List) fromField.get(from);
List list1 = (List) toField.get(to);
List newList = new ArrayList();
if(list != null)
Collections.addAll(newList,list);
if(list1 != null)
Collections.addAll(newList,list1);
toField.set(to, newList);

<!-- end snippet -->

Similar thing with Set - your current code for Set doesn't make any sense, it operates on Class objects.

huangapple
  • 本文由 发表于 2020年8月3日 23:15:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63232134.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定