提问人:Roman Lebedev 提问时间:9/23/2019 最后编辑:Roman Lebedev 更新时间:9/25/2019 访问量:274
Java 接口合成方法生成,同时缩小返回类型范围
Java interface synthetic method generation while narrowing return type
问:
我有 2 个接口和 2 个返回类型。
interface interfaceA {
Publisher<String> doSomething();
}
interface interfaceB extends interfaceA {
Flow<String> doSomething();
}
interface Publisher<T>{}
class Flow<T> implements Publisher<T>{}
所以在运行时,我可以看到 2 个方法interfaceB.class.getMethods()
public default my.package.Publisher my.package.interfaceB.doSomething()
public abstract my.package.Flow my.package.interfaceB.doSomething()
关于第一个,它是合成的。(method.getModifiers() & 0x00001000 > 0) == true
java 会自动生成这种合成方法吗?
它通常如何工作?
答:
Java 语言规范指定了以下内容:
如果 Java 编译器发出的构造与源代码中显式或隐式声明的构造不对应,则必须将其标记为合成构造,除非发出的构造是类初始化方法
我从 Java 论文中看到的另一个定义是:
当封闭类访问嵌套类的私有属性时,Java 编译器会为该属性创建合成方法。
编辑:有人指出,本文所述的一些内容适用于较旧的Java版本(SE7),因此在阅读在线论文时要注意。
例如:
import static java.lang.System.out;
public class Synthetic {
public static void main(String[] arguments) {
Synthetic.NestedClass nested = new Synthetic.NestedClass();
out.println("Age: " + nested.age);
}
private static final class NestedClass {
private String myName = "Tom";
private int age = 42;
}
}
编译器将为正在访问的每个私有属性创建合成方法。因此,它将为 创建合成方法 (),但不会static int access$000(Synthetic$NestedClass)
age
myName
评论
NestedClass
javap
Synthetic$NestedClass.class
NestedClass age
static int access$000(Synthetic$NestedClass);
age
-target
--release
NestedClass
您在这里看到的称为桥接方法。
为了理解为什么需要这样做,我们必须看看 JVM 如何确定两种方法是否不同:
- 每个方法都有一个名称。不同的名称 - >不同的方法。
- 每个方法都有一个描述符。不同的描述符>不同的方法。
描述符包含所有参数和返回类型(对于泛型,它是擦除的)。
从 JVM 的角度来看,它与 是不同的方法,因此当要求它对 进行 invokeinterface 调用时,它不会调用 。Flow doSomething()
Publisher doSomething()
Publisher doSomething()
Flow doSomething()
如果调用站点的目标类型为:interfaceA
intefaceA foo = ...;
foo.doSomething();
但从语言的角度来看,这两种方法是相同的,并且一种会覆盖另一种。
若要还原此关系,请添加一个具有原始方法类型的桥接方法,该方法类型仅调用重载方法。javac
评论