详解Java多态的概念、注意事项和用法
程序员文章站
2024-03-21 20:24:58
...
目录
1 多态概述
概念:
- 多态:同一行为,具有多种不同表现形式。
- 多态是面向对象的三大特征之一(封装、继承、多态)。
- 生活中,比如跑的动作,猫和狗跑起来不同;飞的动作,昆虫和鸟类飞起来不同。可见,同一行为,通过不同的事物,体现出不同的形态。多态描述的就是这种概念。
多态的前提:
- 继承或实现【二选一】
- 方法被重写【不重写,无意义】
- 父类引用子类对象【格式体现】
2 多态的格式
格式:
父类类型 变量名 = new 子类对象;
变量名.方法名();
Fu f = new Zi();
f.method();
父类类型:子类继承的父类类型,或类实现的父接口类型
使用过程:
- 使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,编译错误;
- 如果有,执行的是子类重写后的方法。
代码示例:
// 定义父类
public abstract class Animal {
public abstract void eat();
}
// 定义子类
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("啃骨头");
}
}
// 定义测试类
public class Test {
public static void main(String[] args) {
// 多态形式,创建对象
Animal a1 = new Cat();
// 调用的是Cat的eat
a1.eat();
// 多态形式,创建对象
Animal a2 = new Dog();
// 调用的是Dog的eat
a2.eat();
}
}
吃鱼
啃骨头
3 多态的简单应用
实际开发中,父类类型作为方法形式参数,传递子类对象给方法,进行方法调用,更能体现出多态的扩展性与便利。
// 定义父类
public abstract class Animal {
public abstract void eat();
}
// 定义子类
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("啃骨头");
}
}
// 定义测试类
public class Test {
public static void main(String[] args) {
// 多态形式,创建对象
Cat c = new Cat();
Dog d = new Dog();
showAnimalEat(c);
showAnimalEat(d);
}
public static void showAnimalEat(Animal a){
a.eat();
}
}
吃鱼
啃骨头
4 多态中的类型转换
多态的转型分为向上转型和向下转型两种。
4.1 向上转型
向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
使用格式:
父类类型 变量名 = new 子类类型();
4.2 向下转型
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
格式:
子类类型 变量名 = (子类类型) 父类变量名;
4.2.1 为什么向下转型
当使用多态方法调用方法时,首先检查父类中是否有该方法,如果没有则编译错误。也就是说,不能调用子类拥有而父类没有的方法。所以,想要调用子类特有的方法,必须向下转型。
代码示例:
// 定义父类
public abstract class Animal {
public abstract void eat();
}
// 定义子类
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("啃骨头");
}
public void watchHouse() {
System.out.println("看家");
}
}
// 定义测试类
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat();
// 向下转型
Cat c = (Cat)a;
c.catchMouse();
}
}
吃鱼
抓老鼠
4.2.2 向下转型的异常
向下转型的过程有可能会出现以下异常情况:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();// 调用的是Cat的eat
a.eat();
// 向下转型
Dog d = (Dog)a;
d.watchHouse();//出错
}
}
程序会报出ClassCastException异常,因为Cat类型向上转型,再向下转型必然也是Cat类型,不能是Dog类型,这两个类型没有任何继承关系,不符合类型转换的定义。
4.2.3 向下转型的异常处理办法
为避免向下转型过程中类型转换异常的出现,使用instanceof关键字给引用变量做类型检验。
格式:
变量名 instanceof 数据类型
1 如果变量属于该数据类型,返回true
2 如果变量不属于该数据类型,返回false
所以,在向下转换前,我们最好先做一个判断,代码如下:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat();
// 向下转型
if (a instanceof Cat) {
Cat c = (Cat)a;
c.catchMouse();
} else if (a instanceof Dog) {
Dog d = (Dog)a;
d.watchHouse();
}
}
}
上一篇: 牛顿迭代法求解多项式方程的近似解
下一篇: Java笔记之多态的详解