Java 中的意外多态行为如果重载和覆盖相同的方法

Unexpected Polymorphism Behaviour In Java if same method overloaded and overridden

我一直在我的项目中做一些更改,我发现一些奇怪的或者我会说 Java 中多态性的意外行为。我在下面给出的 Poc 中复制了相同的行为。

1. CommonInterface.java

package com.general;

public interface CommonInterface {

    public void getViews(String str);

    public void getViews(String str, Long id);

}

2。 GenericUtility.java

package com.general;

public class GenericUtility implements  CommonInterface{

    @Override
    public void getViews(String str) {
        System.out.println("This is getViews (single param)from  GenericUtility");
        getViews(str, null);
    }

    @Override
    public void getViews(String str, Long id)  {
        System.out.println("This is getViews (multi-param) from  GenericUtility");
    }

}

3。 CustomUtility.java

package com.general;

public class CustomUtility extends GenericUtility {

    @Override
    public void getViews(String str) {
        System.out.println("This is getViews (single param)from  CustomUtility");
        super.getViews(str);
    }

    @Override
    public void getViews(String str, Long id) {
        System.out.println("This is getViews (multi-param) from  CustomUtility");
        super.getViews(str, null);
    }

}

4. Main.java

package com.general;

public class Main {

    public static void main(String[] args) {
        GenericUtility utility = new CustomUtility();
        String str = "Random String";
        utility.getViews(str);
    }
}

在 运行 Main.java 之后,我的预期输出是

This is getViews (single param)from  CustomUtility
This is getViews (single param)from  GenericUtility
This is getViews (multi-param) from  GenericUtility

但是我得到的输出是

This is getViews (single param)from  CustomUtility
This is getViews (single param)from  GenericUtility
This is getViews (multi-param) from  CustomUtility
This is getViews (multi-param) from  GenericUtility

我无法理解为什么 com.general.GenericUtility#getViews(java.lang.String) 调用 com.general.CustomUtility#getViews(java.lang.String, java.lang.Long)

这是预期的行为吗?我不知道这是什么?

提前致谢。

Java 使用运行时虚拟分派调用实例方法(即非静态方法)。这仍然适用于对 this 的调用;例如,抽象 class 可以定义抽象方法 createResultObject 以由子 class 实现,并在其 doProcessing 方法中使用该方法。

在你的例子中,对象 一个 CustomUtility,因此对 this.getViews(String, String) 的调用被分派给 CustomUtility,然后使用 super 内部。

GenericUtility.getViews(String)调用getViews(str, null);时,将调用的getViews(String, Long)实现是CustomUtility.getViews(String, Long)

那是因为 CustomUtility 也覆盖了该方法。无论从何处调用方法(包括超类),对重写方法的调用都会导致重写实现 运行。唯一可以改变这一点的是子类使用 super.

显式调用该方法

大致情况如下:

  1. main 调用 utility.getViews(str);,这会导致覆盖 CustomUtility.getViews(String) 到 运行.
  2. CustomUtility.getViews(String) 调用 super.getViews(str),这 导致 GenericUtility.getViews(String) 到 运行。
  3. GenericUtility.getViews(String) 调用 getViews(str, null),这 导致 覆盖 CustomUtility.getViews(String, Long) 到 运行 (与您的预期相反)
  4. CustomUtility.getViews(String, Long) 来电 super.getViews(str, null),调用 GenericUtility.getViews(String, Long) 到 运行.