如果重载和覆盖相同的方法,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中的Overload(重载)与Override(重写覆盖)