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

Posted

技术标签:

【中文标题】如果重载和覆盖相同的方法,Java中的意外多态行为【英文标题】:Unexpected Polymorphism Behaviour In Java if same method overloaded and overridden 【发布时间】:2021-08-15 09:21:58 【问题描述】:

我一直在对我的项目进行一些更改,发现一些奇怪的地方,或者更确切地说,我会说 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)

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

提前致谢。

【问题讨论】:

你似乎明白为什么utility.getViews(str) 会调用CustomUtility.getViews。那么你也应该明白为什么GenericUtility中的调用getViews(str, null);(相当于this.getViews(str, null);)会调用CustomUtility中的实现。毕竟,同样的规则适用。 【参考方案1】:

Java 使用运行时虚拟调度来调用实例方法(即非静态方法)。这仍然适用于对this 的调用;例如,抽象类就是这样定义一个抽象方法 createResultObject 以由子类实现并在其 doProcessing 方法中使用该方法。

在你的例子中,对象一个CustomUtility,所以对this.getViews(String, String)的调用被调度到CustomUtility,然后在内部使用super

【讨论】:

谢谢,现在我明白了它是如何工作的。 :)【参考方案2】:

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

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

所以大致是这样的:

    main 调用 utility.getViews(str);,导致覆盖 CustomUtility.getViews(String) 运行。 CustomUtility.getViews(String) 调用 super.getViews(str),其中 导致GenericUtility.getViews(String) 运行。 GenericUtility.getViews(String) 调用 getViews(str, null),其中 导致 覆盖 CustomUtility.getViews(String, Long) 运行 (与您的预期相反) CustomUtility.getViews(String, Long) 来电 super.getViews(str, null),它调用 GenericUtility.getViews(String, Long) 运行。

【讨论】:

以上是关于如果重载和覆盖相同的方法,Java中的意外多态行为的主要内容,如果未能解决你的问题,请参考以下文章

java多态的2种表现形式 方法重载和方法覆盖

8.继承覆盖重载与多态

Java中的Overload(重载)与Override(重写覆盖)

java语言中,overload(重载)和override(覆盖)有何区别?

java中的覆盖,重载和多态

什么是java方法重载