我对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)
1)编译时发生重载,即要定义哪个方法执行是在编译时决定的
2) 您正在将派生类对象引用指定给基类对象
3) 因此,在编译时显然不知道哪个引用了您的基类对象将来将具有,即在运行时
4) 这就是编译器查看中引用类型的原因方法重载的情况
您必须记住,当您定义一个变量类型(如Bass
)时,它只能存储自身的值和从自身派生的类(如Derived
)。
一旦为该变量分配了变量类型,就不能对其进行更改。
一种想法:
假设您的Bass
类存储一个字段值:
class Bass {
String field1;
}
假设您的Derived
类存储了一个附加字段"
class Derived extends Bass {
String field2;
}
现在假设您创建一个低音实例:
Bass bass = new Base();
您可以从对象中访问field1
值。
现在你说你做以下事情:
bass = new Derived();
您仍然可以从对象访问field1
值。但是,您无法访问field2
值,因为低音实例不存储此值。它不符合其结构。
我希望这能帮助您理解为什么当将变量类型设置为其派生类时,它不会更改原始变量类型。