应优先使用getDeclaredMethods()和getDeclaredFields()获取本类全部成员,再调用setAccessible(true)绕过访问限制;public成员可直接用getMethods()/getFields()。

通过 Class 对象动态获取类的方法与字段,核心是调用其提供的 getDeclaredXXX() 和 getXXX() 系列方法,并注意访问权限控制。关键不在于“能不能拿到”,而在于“拿什么”和“怎么用”。
获取方法:区分继承与声明
Class 提供两组方法用于获取方法信息:
- getMethods():返回当前类及其所有父类、接口中声明的 public 方法(含继承来的),但不包括 private/protected/package-private 方法;
- getDeclaredMethods():只返回当前类 自己声明的所有方法,无论 public、private、protected 还是默认访问权限,但不包含从父类或接口继承的方法。
例如,若想调用一个私有方法 private String getValue(),必须先用 getDeclaredMethods() 找到它,再调用 method.setAccessible(true) 破除访问限制,最后用 method.invoke(obj, args) 执行。
获取字段:区分可见性与归属
字段获取逻辑与方法类似:
立即学习“Java免费学习笔记(深入)”;
- getFields():仅返回当前类及父类中所有 public 字段(含继承的 public 字段);
- getDeclaredFields():返回当前类定义的 全部字段,不管修饰符是什么,但不包括父类字段。
读写 private 字段前,必须对 Field 对象调用 field.setAccessible(true);静态字段操作时,field.get(null) 或 field.set(null, value) 中传入 null 作为对象参数。
实际使用中的关键细节
很多问题不是出在“没找到”,而是忽略了几点硬性规则:
- 反射获取的是 运行时类型结构,不是编译期检查结果,所以即使字段是 private,也能拿到并操作;
-
setAccessible(true)是绕过 Java 访问控制的关键步骤,JDK 9+ 默认更严格,某些场景需配合 JVM 启动参数(如--illegal-access=permit); - 调用
invoke()或get()/set()时抛出的异常是包装过的:IllegalAccessException表示权限不足,InvocationTargetException表示被调方法内部抛出了异常,真实异常需通过.getCause()获取。
快速判断该用哪个方法
记住这个口诀:
- 要找“能直接用的 public 成员”→ 用
getXXX()(适合跨类调用、API 兼容场景); - 要“完整解剖本类”→ 用
getDeclaredXXX()(适合序列化、框架底层、测试工具等); - 只要涉及 private/protected → 必须加
setAccessible(true),否则会抛异常。


















