通配符类型、类型擦除和运行时签名:在 A 和 B 继承共同祖先的 <T extends A & B> 上会发生什么?

fge*_*fge 1 java generics type-erasure method-signature

(编辑:评论后修复)

让我们采用一个类或接口A以及一个接口B,其中两者都继承了一个共同的祖先X(假设X不是Object)。让我们有一个方法,它的签名是:

<T extends A & B> void foo(final T arg)
Run Code Online (Sandbox Code Playgroud)

foo运行时的签名是什么?那是void foo(X)or void foo(Object),JVMX在运行时转换为 to吗?

Roh*_*ain 5

类型参数的擦除始终是其最左侧边界的擦除,与继承层次结构中的其他类无关JLS §4.6)。因此,该方法被擦除为:

void foo(final A)
Run Code Online (Sandbox Code Playgroud)

当然,正如注释中所指出的,如果A并且B两者都是类,则该代码将无法编译。类型参数边界不能有多个类作为边界,而只能有一个类,后跟任意数量的接口。

有关类型变量声明的语法,请参见JLS §4.4

TypeParameter:
    TypeVariable TypeBoundopt

TypeBound:
    extends TypeVariable
    extends ClassOrInterfaceType AdditionalBoundListopt

AdditionalBoundList:
    AdditionalBound AdditionalBoundList
    AdditionalBound

AdditionalBound:
    & InterfaceType
Run Code Online (Sandbox Code Playgroud)

任何AdditionalBound都应该是InterfaceType

JVM 在运行时转换为 X?

是的,编译器将添加适当的强制转换,以便代码按预期工作。