Java多态
定义: 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
举例:一种事物的多种形态
- 人动物生物:人既是动物也是生物。
- 牡丹=植物=生物:牡丹既是植物也是生物。
多态的几大必要条件:
- 必须要有继承关系才行。
- 完成继承的同时要有对父类的重写(重写和重载的区别在我的“java面向对象、内存、封装、变量、重载和重载讲解”这篇博客中也有介绍,感兴趣可以去了解一下。
- 有父类的指引变量指向子类的对象(这是java的多态在代码中的体现)。
- 注意:这里所说的父类可以是直接的父类也可以是间接的父类。
这里我多插入一点知识:
- 程序运行分为三个阶段:预编译、编译、运行。
- 预编译:程序打开的时候,活儿已经干完了,(预编译命令,#define)。
- 编译:从打开程序开始到点击左上角的三角形之前–只能识别“=”前面的引用类型,不会识别“=”后面的对象。
- 运行:是从点击三角形开始—真正的识别对象,对象开始干活。
注意:有利于判断多态体系下当父类与子类定义了相同的属性时,对属性和方法的值的判断。- 成员变量:编译的时候能不能访问看父类,运行时看父类。
- 成员方法:编译的时候看父类,运行时看子类。
- 静态方法:编译运行都看父类。
使用多态的方式:
- 子类继承父类方式:
class Animal2 {
String name;
public Animal2() {
super();
// TODO Auto-generated constructor stub
}
public Animal2(String name) {
super();
this.name = name;
}
public void eat() {
// TODO Auto-generated method stub
System.out.println("animal-eat");
}
}
class Dog2 extends Animal2 {//子类继承了父类
public void eat() {
System.out.println("Dog-eat");
}
public void bark() {
System.out.println("Dog-bark");
}
}
class Cat2 extends Animal2 {//子类继承了父类
public void eat() {
System.out.println("Cat-eat");
}
}
public static void main(String[] args) {
//使用多态
//用父类的引用指向子类的对象--这就是java的多态在代码中的体现
//注意:这里所说的父类可以滴直接的父类也可以是间接的父类。
Anima2 dog2 = new Dog2();
dog2.eat();//首先通过Animal保存的地址找到Dog对象,Dog对象再调用show方法
//不能通过的原因:在编译的时候识别的是引用类型,不识别对象,所以识别的只能是Animal中的方法。
}
- 实现接口的方式:
interface Animal {
void eat();
}
class Dog implements Animal {//实现了Animal接口
public Dog() {
super();
// TODO Auto-generated constructor stub
}
public void eat() {
System.out.println("Dog-eat");
}
}
public static void main(String[] args) {
//使用多态
Anima dog = new Dog();
}
- 继承抽象类方式:类似于接口的方式
使用多态的优点:
- 可替换性(substitutability):多态对已存在代码具有可替换性。
- 可扩充性(extensibility):多态对代码具有可扩充性,增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。
- 接口性(interface-ability):多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
- 灵活性(flexibility):它在应用中体现了灵活多样的操作,提高了使用效率。
- 简化性(simplicity):多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
多态的两个重要的点:
- 前提:一定是多态下。
- 两个点:
- 向上转型:相当于自定转型,由地类型向高类型。
- 定义:将子类型转换为父类引用。
- 注意:只是将引用类型转换,与=后没有关系。
- 向下转型:相当于强制类型转换,有高类型到低类型。
- 定义:将父类的引用强制类型转换为子类的引用—调用子类特有的方法。
- 向上转型:相当于自定转型,由地类型向高类型。
- 注意:
- 转型是针对的引用不是类,不能试图用子类的引用指向父类的对象。
- 不是多态的时候不存在向上转型和向下转型。
instanceof运算符:
- 定义:确定全面的对象是不是后面的类或子类的对象,是返回true,不是返回false。
- 前面和后面必须有继承的关系,如果没有会立刻报错。
- 一段实例代码:
public class Demo9 {
public static void main(String[] args) {
Animal3 dog3 = new Dog3();
Animal3 cat3 = new Cat3();
feedAnimal(dog3);
}
public static void feedAnimal(Animal3 animal) {
/*animal.eat();*/
//调用特有的方法
if(animal instanceof Dog3) {
Dog3 dog3 = (Dog3) animal;
dog3.bark();
}
}
}
class Animal3 {
String name;
public Animal3() {
super();
// TODO Auto-generated constructor stub
}
public Animal3(String name) {
super();
this.name = name;
}
public void eat() {
// TODO Auto-generated method stub
System.out.println("animal-eat");
}
}
class Dog3 extends Animal3 {
public void eat() {
System.out.println("Dog-eat");
}
public void bark() {
System.out.println("Dog-bark");
}
}
class Cat3 extends Animal3 {
public void eat() {
System.out.println("Cat-eat");
}
}
总结:
java面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的,多态贯穿于java整个学习,多态就好比将电视从黑白带进了彩色时代。