【教3妹学编程-java基础5】java多态详解
-----------------第二天------------------------
面试中
什么是多态?
面试官:好的, java中的多态你了解吗?
3妹:了解的。
多态是指同一个行为可以有多个不同表现形式的能力。也就是说,在父类中定义的属性和方法,在子类继承后,可以有不同的数据类型或表现出不同的行为。比如针对同一个接口,我们使用不同的实例对象可能会有不同的操作,同一事件发生在不同的实例对象上会产生不同的结果。
多态的作用?
面试官:那使用多态能解决什么问题呢?
3妹:多态机制可以在不修改父类代码的基础上,允许多个子类进行功能的扩展。比如父类中定义了一个方法A,有2个子类继承该父类,这2个子类都重写了方法A。并且子类的方法还可以将自己的参数类型改为父类方法的参数类型,或者将自己的返回值类型改为父类方法的返回值类型。这样就可以动态地调整对象的调用,降低对象之间的依存关系,消除类型之间的耦合,使程序有良好的扩展,并可以对所有类的对象进行通用处理,让代码实现更加的灵活和简洁。
多态的分类
面试官:很好,你再说说多态分哪几种?
3妹:Java中的多态,分为编译时多态和运行时多态。
● 编译时多态:主要是通过方法的重载(overload)来实现,Java会根据方法参数列表的不同来区分不同的方法,在编译时就能确定该执行重载方法中的哪一个。这是静态的多态,也称为静态多态性、静态绑定、前绑定。但也有一种特殊的方法重写的情况,属于编译时多态。在方法重写时,当对象的引用指向的是当前对象自己所属类的对象时,也是编译时多态,因为在编译阶段就能确定执行的方法到底属于哪个对象。
● 运行时多态:主要是通过方法的重写(override)来实现,让子类继承父类并重写父类中已有的或抽象的方法。这是动态的多态,也称为"后绑定"。
总之,如果我们在编译时就能确定要执行的方法属于哪个对象、执行的是哪个方法,这就是编译时多态,否则就是运行时多态!
多态的实现
面试官:好的,这里是纸和笔,请你写一个多态的实现代码。
3妹:好的。
//Parent是父类
public class Parent {
public void say() {
System.out.println("I'm parent");
}
}
//Child是子类
public class Child extends Parent{
@Override
public void say() {
System.out.println("I'm child");
}
}
public class Test {
public static void main(String[] args) {
Parent a = new Parent();
Parent b = new Child();
a.say();//输出I'm parent
b.say(); //输出I'm child
}
}
在这个例子中,变量a编译类型是Parent类,实际类型也是Parent,所以调用say()会执行Parent类的say()方法,打印出I'm parent。
变量b的编译类型也是Parent,但是实际赋值时,给变量b赋值的是Child对象,所以b的实际类型是Child。而Child重写了继承父类Parent,重写了say()方法,所以会调用Child的say()方法,输出 I'm child.
a和b的编译类型相同,却展现出了不同的行为特征,这就是多态。
重写父类的静态方法,父类引用可以调用吗?
面试官: 那如果父类中定义了一个静态方法,子类也定义了一个同名的静态方法,b调用该静态方法,是子类中的还是父类中的呢。
3妹: 会执行父类中的。
如果Parent父类中定义了一个静态方法eat(),子类也定义了一个同名的静态方法eat(),上述代码中b.eat()执行的是Parent类中的eat()方法。在进行向上转型时,父类引用调用同名的静态方法时,执行的是父类中的方法。这是因为在运行时,虚拟机已经确定了static方法属于哪个类。“方法重写”只适用于实例方法,对静态方法无效。静态方法,只能被隐藏、重载、继承,但不会被重写。子类会将父类的静态方法隐藏,但不能覆盖父类的静态方法,所以子类的静态方法体现不了多态,这和子类属性隐藏父类属性一样。
实现代码如下:
//Parent是父类
public class Parent {
public static void eat() {
System.out.println("I'm parent eat");
}
}
//Child是子类
public class Child extends Parent{
public static void eat() {
System.out.println("I'm child eat );
}
}
public class Test {
public static void main(String[] args) {
Parent a = new Parent();
Parent b = new Child();
a.eat();//输出I'm parent eat
b.eat(); //也是输出I'm parent eat
}
}
总结
面试官:好的, 今天的面试就到这里,很高兴你能来参加面试~
3妹:谢谢面试官,再见~
3妹:今天的面试面试的还挺细的,我要总结一下:
- 多态指的是不同子类型的对象,对同一行为作出的不同行为。
- 实现多态要满足继承、重写、向上转型的条件;
- 多态分为编译时多态和运行时多态,我们常说的多态是指运行时多态;
- 方法重载是编译时多态,方法重写是运行时多态,但重写有例外情况;
- 父类引用指向子类对象时,调用的实例方法是子类重写的方法,父类引用不能调用子类新增的方法和子类特有属性;
- 父类引用指向子类对象时,父类引用只会调用父类自己的属性和static方法,不会调用子类的。