1.理解多态性:
可以理解为一个事务的多种形态
2.何为多态性:
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
可以直接应用在抽象类和接口上。
3.Java引用变量有两个类型:
编译时类型和运行时类型。
①编译时类型由声明改变量时使用的类型决定。
②运行时类型由实际赋给该变量的对象决定。
③简称:编译时,看左边;运行时,看右边。
>>若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
>>多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
正常方法的调用
Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();
虚拟方法调用(多态情况下)
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
Person e = new Student();
e.getInfo(); //调用Student类的getInfo()方法
编译时类型和运行时类型
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。 -------动态绑定
多态性的使用举例
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog());
test.func(new Cat());
}
public void func(Animal animal) {
animal.eat();
animal.shout();
}
public void func(Dog dog) {
// 如果没有多态性,只能一个一个写了,你声明什么类型,只能new这个类型的对象,进而显示出多态性的好处
dog.eat();
dog.shout();
}
public void func(Cat cat) {
cat.eat();
cat.shout();
}
}
class Animal {
public void eat() {
System.out.println("动物:进食");
}
public void shout() {
System.out.println("动物:叫");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃骨头");
}
public void shout() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void shout() {
System.out.println("喵喵喵");
}
}
3.方法的重载与重写
二者的定义细节:略
从编译和运行的角度看:
重载,是指允许存在多个同名方法,而这些方法的参数不同,编译器根据方法不同的参数表,对同名的方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定的了。Java重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
而对于多态,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”;
引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就就不是多态。”
4.多态是编译时行为还是运行时行为?如何证明?
import java.util.Random;
//面试题:多态是编译时行为还是运行时行为?
//运行时行为
//证明如下:
class Animal {
protected void eat() {
System.out.println("animal eat food");
}
}
class Cat extends Animal {
protected void eat() {
System.out.println("cat eat fish");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("Dog eat bone");
}
}
public class InterviewTest {
public static Animal getInstance(int key) {
switch (key) {
case 0:
return new Cat();
case 1:
return new Dog();
default:
return new Sheep();
}
}
public static void main(String[] args) {
int key = new Random().nextInt(3);
System.out.println(key);
Animal animal = getInstance(key);
animal.eat();
}
}