如何使用Java Reflection向Collection集合中添加元素?
问题:使用Java反射向Collection字段添加元素
出于学习目的,我想通过Java反射向Collection类型的字段添加元素。我创建了包含Collection<?>类型变量的Collector类,用field.set可以给它设置ArrayList,但直接调用add方法时会抛出IllegalArgumentException异常。
我已经用非反射的方式实现了需求:
if (data instanceof Collection<?>) { collector.getResult().addAll((Collection<?>) data); } else { collector.getResult().add(data); }
但我希望用反射完成同样的操作,以下是我目前的相关代码:
public class Main { public static void main(String[] args) { NotMain1 notMain1 = new NotMain1(); notMain1.setData(Arrays.asList("abc", "bcd", "cde", "def")); NotMain2 notMain2 = new NotMain2(); notMain2.setData("abcdefghi"); try { setResult(notMain1); setResult(notMain2); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } public static void setResult(Object o) throws NoSuchFieldException, IllegalAccessException { Collector collector = new Collector(); Class clazz = o.getClass(); Field data = clazz.getDeclaredField("data"); data.setAccessible(Boolean.TRUE); Object o1 = data.get(o); Class collectorClass = collector.getClass(); Field result = collectorClass.getDeclaredField("result"); result.setAccessible(true); result.set(collector, o1); System.out.println(collector.getResult()); } } class Collector { private Collection<?> result; public Collection<?> getResult() { return result; } public void setResult(Collection<?> result) { this.result = result; } } class NotMain1 { private List<String> data; public List<String> getData() { return data; } public void setData(List<String> data) { this.data = data; } } class NotMain2 { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; } }
解决方案:通过反射实现元素添加
现有代码的问题是直接将目标对象的data字段值赋值给Collector的result字段,这和“添加元素”的需求不符——如果data是单个对象,会直接把result替换成非Collection类型的对象,必然抛出类型异常;同时Collector的result默认是null,无法直接调用add方法。以下是修正后的反射实现:
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; public class Main { public static void main(String[] args) { NotMain1 notMain1 = new NotMain1(); notMain1.setData(Arrays.asList("abc", "bcd", "cde", "def")); NotMain2 notMain2 = new NotMain2(); notMain2.setData("abcdefghi"); try { setResult(notMain1); setResult(notMain2); } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } } public static void setResult(Object o) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Collector collector = new Collector(); Class<?> collectorClass = collector.getClass(); // 初始化Collector的result为可修改的ArrayList Field resultField = collectorClass.getDeclaredField("result"); resultField.setAccessible(true); resultField.set(collector, new ArrayList<>()); // 获取目标对象的data字段值 Class<?> clazz = o.getClass(); Field dataField = clazz.getDeclaredField("data"); dataField.setAccessible(true); Object data = dataField.get(o); // 获取Collection的add/addAll方法,通过反射调用 Collection<?> result = collector.getResult(); if (data instanceof Collection<?>) { Method addAllMethod = Collection.class.getMethod("addAll", Collection.class); addAllMethod.invoke(result, data); } else { Method addMethod = Collection.class.getMethod("add", Object.class); addMethod.invoke(result, data); } System.out.println(collector.getResult()); } } // 以下类保持不变 class Collector { private Collection<?> result; public Collection<?> getResult() { return result; } public void setResult(Collection<?> result) { this.result = result; } } class NotMain1 { private List<String> data; public List<String> getData() { return data; } public void setData(List<String> data) { this.data = data; } } class NotMain2 { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; } }
关键说明
- 初始化Collection:先将Collector的
result字段初始化为ArrayList,避免空指针异常,同时保证集合是可修改的(Arrays.asList返回的是不可修改集合,直接赋值后续add会报错)。 - 反射调用方法:通过
Collection.class.getMethod获取add或addAll方法,再用invoke执行添加操作。由于Java泛型擦除,反射调用时无需关注具体泛型类型,直接传入Object类型参数即可。 - 异常处理:新增
NoSuchMethodException和InvocationTargetException的声明,这两个是反射调用方法时可能抛出的异常。
内容的提问来源于stack exchange,提问作者Thakur Sahab
相关产品推荐
相关产品推荐

