NOTE:个人观点,不保证正确。如有疑问欢迎探讨。
面试被问到的一个题,回来后查了一下资料,整理如下:
题目:
1,请解释下什么是Java的多态。
2,这一过程到底是在编译时还是在运行时决定的?请具体阐明系统是如何做的。
一,多态的概念:
先看个例子:
public class Fruit {
@Override
public String toString() {
System.out.println("Fruit");
}
}
public class Apple extends Fruit {
@Override
public String toString() {
System.out.println("Apple");
}
}
public class Orange extends Fruit {
@Override
public String toString() {
System.out.println("Orange);
}
}
-------------------------------------------------------------------
我们看如下函数输出
Public class Main {
public static void main(String [] args) {
Fruit apple = new Apple();
Fruit orange = new Orange();
Fruit fruit = new Fruit();
System.out.println(apple.toString());
System.out.println(orange.toString());
System.out.println(fruit.toString());
}
}
输出分别是
Apple
Orange
Fruit
我给多态下个定义:程序根据引用所指向的类来确定具体调用哪个被覆盖函数被称为多态性。二,多态的内部实现。
1,编译的角度:
编译器在解析到
Fruit apple = new Apple();
这句的时候,会进行一些合法性的判别。比如如上例子,编译器会延着继承树从Apple开始查找,一直找到Apple所继承的Fruit类。如果Apple没有继承Fruit类或者实现这一接口的话,编译器就会报错。
2,从运行时的角度:
这得从类被加载到内存中开始讲起。
假定有个三个类,它们存在如下继承关系:
ClassA extend ClassB , ClassB extends ClassC,那么在对象ClassA被加载的时候,JVM会先去加载ClassB.由于ClassB又是继承ClassC的,因此JVM在加载ClassB的时候,又会先去加载ClassC.因此,构造顺序是:ClassC,ClassB,ClassA。
因此这三个类在内存(代码区)中的表示将如下所示:
----------------
| ClassA |
----------------
| ClassB |
----------------
| ClassC |
----------------
假定上面三个类中类A和类C都实现了toString()方法,那么在执行如下语句:
ClassB b = ClassA();
b.toString()
b会先到系统代码段找到ClassB所存放的位置,发现里面没有toString()方法,那么它将到它的父类中寻找。这一过程又叫动态联编。