getMethods()返回当前类及所有父类、接口中public方法的并集且自动去重,体现“向上可见的公共契约”;getDeclaredMethods()仅返回当前类声明的所有修饰符方法,不包含继承方法,体现“本类的完整实现细节”。

理解这两个方法的“多态表现”,关键不是它们自身有多态性,而是它们如何体现和响应 Java 的继承与访问控制机制——也就是类在运行时的结构关系。它们不重载、不覆盖,但行为差异直接受类的继承层次和修饰符影响。
getMethods() 体现的是“向上可见的公共契约”
它返回当前类及所有父类、实现接口中 public 方法的并集,且自动去重(同签名只留一个)。这本质上是把类看作一个对外暴露的接口:子类对象能被当作父类或接口类型使用,调用方只关心“能公开做什么”,不关心具体在哪声明。
- 包含 Object 类的 public 方法(如 toString、equals、hashCode、notify 等),哪怕你没显式写
- 若父类 A 有 public void run(),子类 B 没重写,getMethods() 仍会列出 run()
- 若接口 I 声明 public void start(),B 实现 I,该方法也会出现在结果中
- private/protected/default 方法永远不会出现,哪怕在当前类里定义了
getDeclaredMethods() 体现的是“本类的完整实现细节”
它只扫描当前 Class 对象所代表的那个类(或接口)的源码级声明,不管是否可被外部访问,也不管是否从别处继承而来。这是对“类作为代码单元”的忠实映射。
- 返回所有修饰符的方法:public、protected、package-private、private
- 不包含任何继承来的方法,哪怕父类有个 public void init(),子类没重写,也不会出现
- 接口中的 default 方法算作接口“自己声明的”,所以会被 getDeclaredMethods() 返回
- 如果子类重写了父类的 public 方法,getDeclaredMethods() 只返回子类里那个重写版本(即实际声明处)
多态场景下的典型对比
假设 class Dog extends Animal implements Pet,Animal 有 public void eat(),Pet 有 default void play(),Dog 自己定义了 private void bark() 和 public void fetch():
立即学习“Java免费学习笔记(深入)”;
- getMethods() 列出:fetch()、eat()、play()、toString()、equals()…(所有 public + 继承链上的 public + 接口 default)
- getDeclaredMethods() 只列:fetch()、bark()(以及可能的构造器相关桥接方法等),不含 eat() 或 play() ——因为 eat() 在 Animal 里声明,play() 在 Pet 里声明,都不属于 Dog 类的“声明”
这种差异不是 bug,而是设计使然:一个面向调用契约(多态调用视角),一个面向源码结构(实现分析视角)。


















