我基本了解方法覆盖和重载如何在Java中工作。但我的问题是为什么编译器会根据参数的编译类型搜索最具体的方法?换句话说,为什么在方法重载的情况下,它会根据引用的类型而不是对象的类型进行搜索?
检查以下示例
class Base { }
class Derived extends Base { }
class Test {
void foo(Base thing) { System.out.println("foo(Base)"); }
void foo(Derived thing) { System.out.println("foo(Derived)"); }
public static void main(String[] args) {
Test tester = new Test();
Base base = new Base();
tester.foo(base);// 1st call
base = new Derived();
tester.foo(base); // 2nd call
tester.foo(new Derived()); // 3rd call
}
}
实际输出
1st call: foo(Base)
2nd call: foo(Base)
3rd call: foo(Derived)
我期待的输出
1st call: foo(Base)
2nd call: foo(Derived)
3rd call: foo(Derived)
答案 0 :(得分:1)
1)在编译时发生重载,即方法定义为
执行在编译时决定。
2)您将派生类对象引用分配给基类
运行时的对象。
3)所以在编译时显然不知道哪个引用你的
基类对象将来会在运行时使用
4)这就是编译器查看引用类型的原因
方法重载的情况
答案 1 :(得分:0)
您必须记住,当您定义变量类型(例如Bass
)时,它可以存储的唯一值本身以及从自身派生的类,例如Derived
。
一旦为该变量分配了变量类型,就无法更改它。
想到它的一种方法:
假设您的Bass
类有一个存储的字段值:
class Bass {
String field1;
}
假设您的Derived
课程存储了其他字段"
class Derived extends Bass {
String field2;
}
现在说你创建一个低音实例:
Bass bass = new Base();
您可以从对象访问field1
值。
现在你说你做了以下事情:
bass = new Derived();
您仍然可以从对象访问field1
值。
但是,您无法访问field2
值,因为bass实例不存储此值。它不符合其结构。
我希望这可以帮助您理解为什么当设置一个等于其派生类之一的变量类型时,它不会改变原始变量类型。