首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Java字节码/类格式中,是什么决定了一个方法是否覆盖了另一个方法?

在Java字节码/类格式中,是什么决定了一个方法是否覆盖了另一个方法?
EN

Stack Overflow用户
提问于 2021-09-08 11:52:22
回答 2查看 189关注 0票数 1

我知道字节码规范允许类具有相同签名的方法,与Java语言不同的是返回类型不同。有些语言甚至在某些情况下使用这种语言。我的问题与反思有关:

如果在一个类中我发现一个(非私有)方法的名称和参数类型与它的超类(非最终的、非私有的)相同,并且返回类型等于或是超类中该方法的返回类型的一个子类型,那么我什么时候可以假设静态调用'supermethod‘的代码总是会导致’重写(?)‘的执行。方法(自然地假设调用是对属于该类的对象进行的)?即使在编译到JVM字节码的其他语言中,或者如果涉及运行时代码生成,还是被黑客入侵的合成类(如lambda转发器)?

我的问题是注意到在Scala标准库中,Iterable[E]是如何有一个方法的:

代码语言:javascript
复制
def map[O](f :E => O) :Iterable[E]

Map[K, V]中,Iterable[(K, V)]的子类声明另一个方法:

代码语言:javascript
复制
def map[A, B](f :((K, V)) => (A, B)) :Map[A, B]

实际签名比这里更复杂,但原理是相同的:擦除后,Map中的方法可以覆盖Iterable中的方法。

EN

Stack Overflow用户

回答已采纳

发布于 2021-09-08 21:25:44

重写的事实由JVM根据方法描述符的完全相等(包括参数类型和返回类型)来决定。见JVMS §5.4.5第5.4.6条

因此,在JVM级别上,返回Map的方法不会覆盖返回Iterable的方法。编译器通常生成一个返回Iterable的桥方法,该方法是用一个简单的委托实现的,该方法返回Map

示例:

代码语言:javascript
复制
class A<T extends Iterable> {
    T map() {
        return null;
    }
}

class B extends A<Collection> {
    @Override
    Collection map() {
        return null;
    }
}

这里,B.map重写A.map,尽管返回类型不同。为了使这种层次结构成为可能和有效,编译器生成(在字节码级别上)另一个返回Iterable的方法Iterable

代码语言:javascript
复制
class B extends A<java.util.Collection> {
  B();
       0: aload_0
       1: invokespecial #1                  // Method A."<init>":()V
       4: return


  java.util.Collection map();
       0: aconst_null
       1: areturn


  java.lang.Iterable map();
       0: aload_0
       1: invokevirtual #7                  // Method map:()Ljava/util/Collection;
       4: areturn

当在B的实例上调用虚拟方法B.map:Iterable时,总是调用方法B.map:Iterable,后者依次调用B.map:Collection

票数 4
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69102562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档