Java反射设置非静态字段触发IllegalArgumentException的问题解决
解决Java反射设置非静态字段的IllegalArgumentException异常
问题原因
非静态成员字段属于类的实例对象,而非类本身。使用Field.set(Object obj, Object value)方法时:
- 若字段是静态字段,第一个参数
obj可以传入类的Class对象或null; - 若字段是非静态字段,第一个参数
obj必须传入该字段所属类的实例对象。
你的代码中给非静态字段resolver传入了Class对象(clazz),JVM因此抛出异常,提示无法将字段赋值给java.lang.Class类型的对象。
解决方案
为非静态字段赋值前,先创建类的实例对象,再将实例传入Field.set()方法:
修正后的代码
Reflections reflections = new Reflections("abc.test", new SubTypesScanner(false)); Set<Class<?>> classes = reflections.getSubTypesOf(Object.class); for (Class<?> clazz : classes) { try { Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields()) .filter(f -> VariableResolver.class.isAssignableFrom(f.getType())) .findFirst(); if (!optional.isPresent()) { continue; } Field field = optional.get(); field.setAccessible(true); // 创建类的实例(假设类有无参构造) Object instance = clazz.getDeclaredConstructor().newInstance(); // 传入实例对象为非静态字段赋值 field.set(instance, new DefaultVariableResolver()); // 若需保留实例供后续使用,可在此处做存储等操作 } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } }
注意事项
- 如果目标类没有无参构造方法,需要通过
clazz.getConstructor(参数类型...)获取对应构造器,再传入参数创建实例; - 若构造方法是私有修饰,需先调用
constructor.setAccessible(true)允许反射访问。
验证
去掉TestClass中resolver字段的static修饰符,运行修正后的代码,即可正常为非静态字段赋值,不会再触发IllegalArgumentException。
内容的提问来源于stack exchange,提问作者Bin
相关产品推荐
相关产品推荐

