正确:父类private方法不能被子类直接调用;必须通过反射获取Parent.class.getDeclaredMethod()并setAccessible(true)后,才能在子类实例上调用。

明确目标:父类私有方法不可被子类直接调用
Java 中,private 方法只在声明它的类内部可见,即使子类继承了父类,也无法通过 this.privateMethod() 或 super.privateMethod() 调用。这不是语法错误,而是编译期强制限制。要“动态调用”,必须借助反射——它在运行时操作字节码元数据,不走常规继承链校验。
核心步骤:从父类 Class 获取并放开访问
关键不在子类,而在**显式指向父类的 Class 对象**,再获取其声明的方法:
- 用
Parent.class.getDeclaredMethod("methodName")获取方法对象(不能用getClass().getDeclaredMethod(),那只会查子类自身声明) - 立即调用
method.setAccessible(true)关闭语言级访问检查 - 调用时传入子类实例(
method.invoke(childInstance)),JVM 允许私有方法在其声明类的实例上执行
注意继承关系下的常见陷阱
以下情况容易出错,需特别留意:
- 若父类方法被子类重写(override),反射仍调用的是父类原始实现,与多态无关
- 若父类是泛型类或含桥接方法,
getDeclaredMethod需严格匹配参数类型,建议用getDeclaredMethods()遍历筛选 - 在 JDK 9+ 模块系统中,如果父类来自
java.base等强封装模块,反射会抛InaccessibleObjectException,除非 JVM 启动时加--add-opens - 异常处理不能只捕获
IllegalAccessException,还需处理InvocationTargetException(原方法抛的异常会被包装)
一个可运行的简化示例
假设父类 Parent 有 private void log(),子类 Child extends Parent 想在自己的方法中调用它:
public void invokeParentLog() {
try {
Method method = Parent.class.getDeclaredMethod("log");
method.setAccessible(true);
method.invoke(this); // this 是 Child 实例,但方法属于 Parent
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
这段代码在 JDK 8 及多数开发环境有效;生产环境部署前,务必验证模块开放策略和 JVM 版本兼容性。










