首页 > 解决方案 > 在 Java 中重载重写的方法

问题描述

我有一个实现接口 A 的类 B ,这样:

public interface A {

    Map<String, Object> doStuff(Integer param1, Integer Param2);
}

public class B implements A {

    public Map<String, Object> doStuff(Integer param1, Integer param2) {
        return doStuff(param1, param2, newParam3);
    }

    public Map<String, Object> doStuff(Integer param1, Integer Param2, boolean param3) {
        if (param3)
            doSomething;
        return doneStuff;
    }
}

但是当我尝试访问重载但未覆盖的方法时,我会遇到编译时错误。这不应该很好吗?

标签: javainheritance

解决方案


java 方法调用中有两个完全独立的步骤。

第 1 步是:将方法调用(在您的源代码中)转换为完全限定的方法 ID。这完全发生在编译时

第 2 步是:现在我们有了一个完全限定的方法 ID,通过动态查找找到该 ID的实际实现x.getClass(),从对象的实际实例类型 ( ) 开始,然后在层次结构中向上直到找到实现。这完全发生在运行时

完全限定的方法 ID 包括包、类、方法名称、参数类型返回类型

因此,在您的 B 类中,您有2 个不同的方法 ID。并且不同的方法ID是不同的方法;名称相同的事实无关紧要。

换句话说,这:

A x = new B();
x.doStuff(param1, param2);

存储为方法的 INVOKEVIRTUAL/INVOKEINTERFACE com.foo.pkg.A::doStuff(Ljava/lang/Integer;L/java/lang/Integer;)Ljava/util/Map;。这实际上是在类文件中;看看输出javap或者用十六进制编辑器打开那个东西,你会在那里找到那个字符串,至少,从doStuff.

然后仅在运行时,'INVOKEINTERFACE com.foo.pkg.A doStuff(Ljava/lang/Integer;L/java/lang/Integer;)Ljava/util/Map bytecode instruction ends up checking the type of the object that yourx variable is pointing to, figures out it's an instance ofcom.foo.pkg.B`,然后实际上调用 B 的这个方法的实现来完成这项工作。

您的第二个 doStuff 方法具有方法 ID B doStuff(Ljava/lang/Integer;Ljava/lang/Integer;Z)Ljava/util/Map;- 请注意这只是一种完全不同的方法(这个方法中有一个 Z)。

因此,这:

A x = new B();
x.doStuff(1, 2, true);

是编译错误:A 接口根本没有那个方法。


推荐阅读