Java 从基类方法调用基类重写函数
我希望这段代码能够输出:Java 从基类方法调用基类重写函数,java,oop,theory,overloading,Java,Oop,Theory,Overloading,我希望这段代码能够输出: public class A { public void f1(String str) { System.out.println("A.f1(String)"); this.f1(1, str); } public void f1(int i, String str) { System.out.println("A.f1(int, String)"); } } public clas
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
public class B extends A {
@Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
@Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.f1("Hello");
}
}
但我得到了:
B.f1(String)
A.f1(String)
A.f1(int, String)
我知道在B的上下文中,A.f1(字符串)中的“this”是B的实例。
我是否可以选择执行链new B1().f1(字符串)->(A的)f1(字符串)->(A的)f1(int,字符串)
这是一个理论上的问题,实际上,解决方案显然是实现一个f1(String)和f1(int,String)都将调用的私有函数
谢谢你,Maxim.Java中重写的方法是动态绑定的。i、 e.对象的实际实例的类型决定了将调用什么
final
方法(不能重写)和private
方法(不能继承)是静态绑定的
在C++中,对比度,你必须明确地使函数
B.f1(String)
A.f1(String)
B.f1(int, String)
A.f1(int, String)
不幸的是,没有
我相信您一定知道,但为了完整性,我将明确声明-只有两个关键字可以控制方法调用:
- this-
-查找从调用实例的类开始的方法(实例的“top”虚拟表-隐含默认值)this.method()
- super-
-查找从定义调用方法的类的父类开始的方法(调用类的“父虚拟表”,但这种方式更简单-谢谢@maaartinus)super.method()
- current-
-查找从定义调用方法的类开始的方法current.method()
但是Java没有这样的关键字(还没有?)。我尝试使用反射(为a的f1(int,String)获取一个方法对象并调用它),但没有成功。Sun博客中的[blog entry][1]指出,这在Java中是不可能的。[1] :AFAIK,
super.method()。好吧,它是用invokespecial编译的。@maaartinus-谢谢-啊,我喜欢每天学习新东西。因此,没有invokevirtualstartingfromparent
指令-invokespecial
用于super
调用,而invokespecial
使用编译时绑定。因此,在调用super
时,我们对类型有足够的了解,可以对目标方法进行编译时解析。如果该方法没有在直接超类中实现,那么我假设仍然需要向上搜索层次结构。最终结果实际上是一样的吗?我认为在运行时没有任何查找,即使在这种情况下也没有。IIUIC,super
实际上是指拥有它的始祖。编译器必须知道整个层次结构,以便在类文件中写入正确的祖先。如果该方法不存在(这只能通过使用另一个类文件的技巧来实现),将抛出一个NoSuchMethodError。@maartinus-同意,该方法始终在编译时解决。我的意思是在编译时“搜索的等价物…仍然是必需的”,因此最终结果是一样的——找到并调用层次结构上最近的方法。这个问题已经有3年多的历史了。您只需发布一些代码而不做任何解释。您设计中的另一个缺陷是类a
需要知道它的所有子类(B
,在这个简单的例子中),如果您想创建一个新的子类,这是很困难的,因为您还必须调整类a
。在方法调用前面加上this.
总是多余的。
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
privateF1(1, str);
}
private void privateF1(int i, String str) {
System.out.println("A.f1(int, String)");
}
public void f1(int i, String str) {
privateF1(i, str);
}
}
package main;
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
if (this instanceof B)
new A().f1(1, str);
else
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
class B extends A {
@Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
@Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
public static void main(String[] args) {
A a = new B();
a.f1("Hello");
}
}