Java中的多态


提示:以下是本篇文章正文内容

一、Java中的多态

多态,就是方法或对象有多种形态,包括方法的多态和对象的多态。

1. 方法的多态:

重写override和重载overload就体现多态,重写和重载不多赘述。
在这里插入图片描述

2. 对象的多态 (关键)

编译类型 对象名 = new 运行类型();
编译类型:简单理解 javac 编译时看的类型,要编译过的去不能报语法错误;
运行类型:过了编译阶段,到了运行阶段 java 要看的类型。

编译类型看 = 的左边,运行类型看 = 的右边:
如:Animal animal = new Dog();
对象animal的编译类型是Animal,运行类型是Dog

二、对象的多态 (关键)

1.多态的向上转型

(可以调用父类中所有的成员,但执行的方法是子类中重写的方法)
语法:
父类类型 父类引用名 = new 子类类型();

// 向上转型:父类的引用名 指向 子类的对象   
Animal animal = new Cat();
Object object = new Cat(); // 父类可以不是直接父类
注意两点:

编译类型 对象名 = new 运行类型();

1)编译阶段:能调用哪些成员,是由编译类型决定的,所以父类引用名,不能调用子类特有的成员,否则编译不通过直接报错;
2)运行阶段:如果调用的是方法,则由运行类型决定,调用方法要从子类开始查找,一般调用的就是子类重写的方法;如果调用的是属性,就直接看编译类型,也调用的是父类属性!!!(要记住,属性无重写)
Animal animal = new Cat();
animal.catchMouse(); // 编译报错!catchMouse是子类Cat特有的方法
animal.eat(); // 调用子类Cat重写的方法,猫吃鱼...
class Base{ // 父类
	int count = 10;
	public void display(){System.out.println(this.count);} 
}
class Sub extends Base{ // 子类
	int count = 20;
	public void display(){System.out.println(this.count);}
}
// main中调用
public static void main(String[] args){
	Sub sub = new Sub(); 
	Base base = sub; // 向上转型
	System.out.println(base.count); // 输出10,调用父类中的count
	base.display(); // 输出20,调用子类中的display()
}

2.多态的向下转型

(可以调用子类中所有的成员)
语法:
子类类型 子类引用名 = (子类类型)父类引用;
向下转型,要和向上转型结合起来思考,后面的父类引用是向上转型产生的。

注意两点:
1)只能强转父类的引用,不能强转父类的对象;
2)强转的父类引用,先前已经指向要强转类型 (子类) 的对象;

也就是向下转型是和向上转型结合起来的,
向上转型:Animal animal = new Cat();
向下转型:Cat cat = (Cat) animal;
向下转型:Dog dog = (Dog) animal; // 错误!!animal此时指向Cat对象

Animal animal = new Cat();
Cat cat = (Cat) animal;
cat.CatchMouse(); // 调用Cat类中特有的猫抓老鼠方法

总结

为何需要向上转型和向下转型 ?

1. 向上转型:父类引用可以调用子类中重写父类的方法,这样当需要添加新功能时,新增一个子类即可,而不需要更改父类代码;
Animal animal = new Dog(); 
animal.eat(); // 会调用Dog类中的eat方法;
animal = new Cat(); 
animal.eat(); // 又会调用Cat类中的eat方法;
2. 向下转型:一般是为了重新获得因为向上转型而失去的子类特性,所以向下转型前一般都有向上转型,也会结合instanceOf使用;
Animal animal = new Dog();
Dog dog = (Dog) animal; // 为了使用Dog类中独有的属性和方法

animal = new Cat();  
Cat cat = (Cat) animal; // 为了使用Cat类中独有的属性和方法
### Java多态的具体表现形式 #### 接口实现多态Java中,除了通过继承来实现多态外,还可以利用接口达到相同的效果。一个类能够实现多个接口,并且不同类可以各自实现相同的接口却表现出各异的行为模式[^2]。 ```java interface Flyable { void fly(); } class Bird implements Flyable { @Override public void fly() { System.out.println("Bird is flying"); } } class Airplane implements Flyable { @Override public void fly() { System.out.println("Airplane is flying at high speed."); } } ``` #### 继承层次中的方法重写 当子类覆盖来自其父类方法时,在运行期间会根据实际对象类型决定执行哪个版本的方法——这便是动态绑定机制发挥作用之处。即使声明类型的引用指向某个特定实例,只要该实例所属的最具体类中有相应方法定义,则优先调用后者[^3]。 ```java public class Animal { public void makeSound(){ System.out.println("Animal sound..."); } } public class Dog extends Animal{ @Override public void makeSound(){ System.out.println("Woof woof!"); } } // 测试代码片段 Animal myPet = new Dog(); // 编译器只知道myPet是一个Animal类型 myPet.makeSound(); // 输出 "Woof woof!" 而不是默认动物叫声 ``` #### 使用 `instanceof` 关键字安全转型 为了防止因强制转换失败而导致程序崩溃(`ClassCastException`)的情况发生,可以在尝试向下造型之前先检查目标对象是否确实属于预期类别之一。如果条件成立则继续操作;反之则采取其他措施处理未知情况[^1]。 ```java if (object instanceof String){ String str = (String)object; } else { // Handle non-string objects here. } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值