1.多态性的理解
可以理解为一个事物的多种形态。
2.何为多态性
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
举例:
//对象的多态性:父类的引用指向子类的对象
Person p2 = new Man();
// Person p3 = new Woman();
3.多态性的使用
4.多态性的使用前提
① 需要存在继承或者实现关系
②有方法的重写
③要有父类指针(引用)指向子类对象。
5.多态性的应用举例
Person p2 = new Man();
// Person p3 = new Woman();
//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
p2.eat();
p2.walk();
6.多态性使用的注意点
对象的多态性,只适用于方法,不适用于属性(调用属性时编译和运行都看左边)
7.关于向上转型与向下转型:
7.1 向上转型
子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)
7.2 向下转型
使用强制类型转换符。
7.2.1 为什么使用向下转型:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用,使用向下转型才能调用子类特有的属性和方法?
7.2.2 如何实现向下转型
person p2 = new Man();
Man m1 = (Man)p2;
m1.earnMoney();
m1.isSmoking = true;
//练习:
//问题一:编译时通过,运行时不通过
//举例一:
// Person p3 = new Woman();
// Man m3 = (Man)p3;
//举例二:
// Person p4 = new Person();
// Man m4 = (Man)p4;
//问题二:编译通过,运行时也通过
// Object obj = new Woman();
// Person p = (Person)obj;
//问题三:编译不通过
// Man m5 = new Woman();
// String str = new Date();
// Object o = new Date();
// String str1 = (String)o;
7.2.3 使用时的注意点
为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先 进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。 如果 a instanceof A返回true,则 a instanceof B也返回true. 其中,类B是类A的父类。
//使用强转时,可能出现ClassCastException的异常。
// Woman w1 = (Woman)p2;(此时P2是引用的是Man对象)
// w1.goShopping();
7.2.4 instanceof的使用
a instanceof A: 判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先 进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。 如果 a instanceof A返回true,则 a instanceof B也返回true. 其中,类B是类A的父类。
7.2.5 图示
Person p2 = new Man();
if(p2 instanceof Woman){
Woman w1 = (Woman)p2;
w1.goShopping();
System.out.println("******Woman******");
}
if(p2 instanceof Man){
Man m2 = (Man)p2;
m2.earnMoney();
System.out.println("******Man******");
}
if(p2 instanceof Person){
System.out.println("******Person******");
}
if(p2 instanceof Object){
System.out.println("******Object******");
}
8. 面试题
8.1 谈谈你对多态性的理解?
多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
8.2 多态是编译时行为还是运行时行为?
运行时行为
//证明如下:
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");
}
}
class Sheep extends Animal {
public void eat() {
System.out.println("Sheep eat grass");
}
}
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();
}
}