在Java中,父类引用对象调用子类对象的原理涉及到两个关键概念:编译时类型和运行时类型。
-
编译时类型(Compile-time Type):
- 编译时类型是指在编写代码时,你所声明的引用的类型。例如,如果你有一个声明为
Animal animal
的引用,编译时类型就是Animal
。
- 编译时类型是指在编写代码时,你所声明的引用的类型。例如,如果你有一个声明为
-
运行时类型(Runtime Type):
- 运行时类型是指在程序运行时实际指向的对象的类型。如果在运行时,
animal
引用实际上指向了一个Dog
对象,那么运行时类型就是Dog
。
- 运行时类型是指在程序运行时实际指向的对象的类型。如果在运行时,
Java中的多态性允许你使用父类的引用来引用子类的对象。这意味着,你可以将一个子类的对象分配给一个父类的引用,然后通过这个父类的引用调用在父类和子类中都存在的方法。
示例代码:
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
public void fetch() {
System.out.println("Dog fetches a ball");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog(); // 编译时类型是Animal,运行时类型是Dog
animal.sound(); // 调用的是Dog类的sound方法,输出 "Dog barks"
// 下面的代码无法通过编译,因为编译时类型是Animal,编译器只知道Animal类的方法
// animal.fetch(); // 编译错误
// 若要调用子类特有的方法,需要将引用强制转换为子类类型
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.fetch(); // 可以调用Dog类的fetch方法
}
}
}
总的来说,Java的多态性允许你在编写代码时使用通用的父类引用,然后在运行时实际指向子类对象,这样你可以在不知道对象的具体类型的情况下调用相同的方法。当然,要注意在使用时确保引用的运行时类型是正确的,否则可能会引发ClassCastException
。