首先,对术语的澄清:我们将一个对象分配给类型为 的变量。 是对碰巧是 的子类型的对象的引用。Child
Parent
Parent
Parent
Child
它仅在更复杂的示例中有用。想象一下,您添加到类父级:getEmployeeDetails
public String getEmployeeDetails() {
return "Name: " + name;
}
我们可以重写该方法以提供更多详细信息:Child
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
现在,您可以编写一行代码来获取任何可用的详细信息,无论对象是 a 还是 :Parent
Child
parent.getEmployeeDetails();
下面的代码:
Parent parent = new Parent();
parent.name = 1;
Child child = new Child();
child.name = 2;
child.salary = 2000;
Parent[] employees = new Parent[] { parent, child };
for (Parent employee : employees) {
employee.getEmployeeDetails();
}
将产生以下结果:
Name: 1
Name: 2 Salary: 2000
我们使用 a 作为 .它具有该类独有的特殊行为,但是当我们调用时,我们可以忽略差异并专注于如何和相似。这称为亚型多态性。Child
Parent
Child
getEmployeeDetails()
Parent
Child
更新后的问题询问了当对象存储在引用中时,为什么无法访问该对象。答案是“多态性”和“静态类型”的交集。因为Java在编译时是静态类型的,所以你从编译器那里得到了某些保证,但你被迫遵循规则作为交换,否则代码将无法编译。在这里,相关的保证是子类型的每个实例(例如)都可以用作其超类型的实例(例如)。例如,可以保证,当您访问或定义方法或字段时,可以保证在任何非空对象上定义方法或字段,这些对象可以分配给类型的变量。为了保证这一点,编译器在决定可以访问的内容时只考虑该静态类型(基本上是变量引用的类型)。因此,您无法访问在对象的运行时类型 上定义的任何成员。Child.salary
Child
Parent
Child
Parent
employee.getEmployeeDetails
employee.name
employee
Parent
Parent
Child
当你真的想使用a作为一个,这是一个容易接受的限制,你的代码将可用于及其所有子类型。如果这是不可接受的,请创建引用的类型。Child
Parent
Parent
Child