Java中具有不同参数数据类型的继承和重载方法
当我分析一个与重载和继承相关的简单java代码时,我希望收到一个重载匹配参数数据类型的输出。但不是这样的 代码: 输出:Java中具有不同参数数据类型的继承和重载方法,java,inheritance,polymorphism,overloading,overriding,Java,Inheritance,Polymorphism,Overloading,Overriding,当我分析一个与重载和继承相关的简单java代码时,我希望收到一个重载匹配参数数据类型的输出。但不是这样的 代码: 输出: num1 Type: java.lang.Integer num2 Type: java.lang.Long a1 Type: D a2 Type: D calc A calc A Number: 22 我在这里测试代码: 您的主要问题似乎是为什么类型输出与正式类型不匹配。这完全是有意为之,这就是为什么面向对象编程如此强大的原因 在实例上调用方法时,运行时系统会查看实例的实
num1 Type: java.lang.Integer
num2 Type: java.lang.Long
a1 Type: D
a2 Type: D
calc A
calc A
Number: 22
我在这里测试代码:
您的主要问题似乎是为什么类型输出与正式类型不匹配。这完全是有意为之,这就是为什么面向对象编程如此强大的原因 在实例上调用方法时,运行时系统会查看实例的实际类型,并根据其实际类型而不是形式类型查找要调用的方法 如果不是这样,你将无法完成任何有用的事情。您希望能够声明一个抽象类
A
,具体类B
和C
以不同的方式实现细节。但是您还希望能够声明A
类型的变量,而不必关心它们来自何处,以及它们实际上是B
类型还是C
类型。然后,您可以调用作为A
契约一部分的方法,它将做正确的事情:真正的B
将调用B
的实现,同样地,对于C
至于为什么最终调用A
的calc
方法而不是D
,这也是因为多态性的工作方式。变量的形式类型是A
;因此,当您调用.calc()
时,类型系统将:
A
中找到最合适的方法来匹配编译时的调用李>
A
和实际类型之间重写该属性李>
A
的版本calc()
方法:您提供了具有不同签名的方法。因此,在步骤1(编译时)中,类型系统找到A.calc(double)
;在步骤2中(在运行时),它发现这并没有在类层次结构的更底层被覆盖;因此,在步骤3(运行时)中,它调用A
的版本
重载在编译时根据形式类型解决;重写在运行时根据实际类型进行解析。这是因为这些方法是重载,而不是原始
calc
方法的重写。因此,如果您使用的是a
类型的引用,则可以看到的都是最初属于a
的方法。所有其他方法都隐藏在对象中,就像您用新名称编写它们一样
因此,当编译器必须决定为每次计算调用哪个方法时,它并没有您认为它拥有的所有选项。它只有原始的calc(double)
,因此它将调用编译为“将值转换为double并调用calc(double)
”。在编译时,它不知道实际的类不是A
。它不能编译成这样的代码:“在运行时检查是否有一个名为calc(int)
,如果有,就使用它,如果没有,就转换成double并使用calc(double)
。它需要知道在编译时放在那里的指令是什么。那时,它所知道的关于这个引用的所有信息都是a
根据评论进行编辑:
编译器总是使用引用类型的约定来选择要调用的方法。也就是说,变量的类型,在本例中是A
无论实际对象是否具有重写方法,都会发生这种情况。此时,编译器不知道它。它所做的是告诉运行时环境:“当到达这一点时,获取实际对象,并使用此签名运行方法:calc(double)
”
因此,如果在运行时,实际对象也有calc(int)
和calc(long)
以及其他名为calc
的方法,这并不重要,因为编译器说“使用calc(double)
”
现在,如果运行时对象有一个重写calc(double)
,则运行时环境将采用它,而不是原始的calc(double)
,因为这是重写的本质
总而言之:
calc(double)
。如果它有覆盖,它将使用该覆盖。如果它只有原件,它将使用它我认为调用这样一个重载方法,首先将调用实际的类方法(在本例中为D)(不是变量->A中的一个),如果不匹配,契约将转到父类,依此类推。。。在这段代码中就是这样工作的:@carvallo在您链接到的代码中,这是一个覆盖,而不是重载。覆盖具有相同的名称和相同的参数列表;重载具有相同的名称,但参数列表不同。实际上,重载方法是一种完全不同的方法。好吧,我知道第二个例子是重写。。。所以,只是为了检查我是否理解得很好:在重写中,VM选择与对象(而不是变量)契约匹配的方法(在运行时),在重载中,编译器根据调用它的变量的类型选择方法。如果它是这样工作的,那么让我困惑的是,在我的示例中,当我检查两种情况下的对象类型时,它都返回D,但存储
num1 Type: java.lang.Integer
num2 Type: java.lang.Long
a1 Type: D
a2 Type: D
calc A
calc A
Number: 22