Java 接口(interface)合成方法生成,同时缩小返回类型

标签 java inheritance jvm

我有 2 个接口(interface)和 2 个返回类型。

interface interfaceA {
   Publisher<String> doSomething();
}

interface interfaceB extends interfaceA {
   Flow<String> doSomething();
}

interface Publisher<T>{}
class Flow<T> implements Publisher<T>{}

所以在运行时,我可以看到interfaceB.class.getMethods()的2个方法

  1. 公共(public)默认 my.package.Publisher my.package.interfaceB.doSomething()

  2. 公共(public)抽象 my.package.Flow my.package.interfaceB.doSomething()

关于第一个,它是合成的。 (method.getModifiers() & 0x00001000 > 0) == true

java会自动生成这个合成方法吗?

一般来说它是如何工作的?

最佳答案

您在这里看到的称为桥接方法。

要理解为什么需要这样做,我们必须看看 JVM 如何确定两个方法是否不同:

  • 每个方法都有一个名称。不同的名称 -> 不同的方法。
  • 每个方法都有一个描述符。不同的描述符->不同的方法。

描述符包含所有参数和返回类型(使用泛型,它会被删除)。

从 JVM 角度来看,Flow doSomething() 是与 Publisher doSomething() 不同的方法,因此当要求它对 Publisher 执行 invokeinterface 调用时doSomething() 它不会调用 Flow doSomething()

如果调用站点的目标类型为 interfaceA,就会发生这种情况:

intefaceA foo = ...;
foo.doSomething();

但是从语言的角度来看,这两种方法是相同的,并且一种方法会覆盖另一种方法。

为了恢复这种关系,javac 添加了一个桥接方法,其原始方法类型仅调用重载方法。

关于Java 接口(interface)合成方法生成,同时缩小返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58065680/

相关文章:

java - fileChooser.setDialogType() 不起作用

javascript - 如何在具有多个继承属性的 Javascript 中表示分层产品目录 [分类法]?

C++ 和 Sfml 继承不起作用

java - 不同操作系统上的 JVM 性能差异

java - 使用可维护性代理打开核心转储时出现错误 "windbg error:OpenDumpFile failed"

Java私有(private)静态内部类

java - 更新 JFrame 中的 JPanel

java - 序列化热点状态

java - Spring 3.x - 如何从返回数据的映射重定向?

c++ - 基访问派生的 friend