基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
多态的具体体现
- 方法的多态:重写和重载就体现多态.
- 对象的多态(重点)
```java
public class Animal {
public void cry() {
} }System.out.println("Animal cry() 动物在叫....");
public class Cat extends Animal { public void cry() { System.out.println(“Cat cry() 小猫喵喵叫…”); } }
public class Dog extends Animal { public void cry() { System.out.println(“Dog cry() 小狗汪汪叫…”); } }
public class PolyObject { public static void main(String[] args) { //体验对象多态特点 //animal 编译类型就是 Animal , 运行类型 Dog Animal animal = new Dog(); //因为运行时 , 执行到改行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cry animal.cry(); //小狗汪汪叫 //animal 编译类型 Animal,运行类型就是 Cat animal = new Cat(); animal.cry(); //小猫喵喵叫 } }
<a name="1ccfe472"></a>
## 编译类型和运行类型
1. 一个对象的编译类型和运行类型可以不一致
2. 编译类型在定义对象时,就确定了,不能改变
3. 运行类型是可以变化的.
4. 编译类型看定义时=号的左边,运行类型看=号的右边
<a name="fb21c157"></a>
## 多态注意事项和细节
1. 多态的**前提**是:两个对象(类)存在继承关系
2. 多态的向上转型
- 本质:父类的引用指向了子类的对象
- 语法: `父类类型 引用名 = new 子类类型();`
- 特点:**编译类型看左边,运行类型看右边**。可以调用父类中的所有成员(需遵守访问权限),**不能调用子类中特有成员;最终运行效果看子类的具体实现**!
3. 多态向下转型
- 语法: `子类类型 引用名 = (子类类型) 父类引用;`
- 只能强转父类的引用,不能强转父类的对象。
- 要求父类的引用必须指向的是当前目标类型的对象。
- 当向下转型后,可以调用子类类型中所有的成员。
示例代码:
```java
public class Animal {
String name = "动物";
int age = 10;
public void sleep(){
System.out.println("睡");
}
public void run(){
System.out.println("跑");
}
public void eat(){
System.out.println("吃");
}
public void show(){
System.out.println("hello,你好");
}
}
public class Cat extends Animal {
public void eat(){//方法重写
System.out.println("猫吃鱼");
}
public void catchMouse(){//Cat 特有方法
System.out.println("猫抓老鼠");
}
}
public class Dog extends Animal {}
public class PolyDetail {
public static void main(String[] args) {
//向上转型: 父类的引用指向了子类的对象
Animal animal = new Cat();
Object obj = new Cat();//可以吗? 可以。Object 也是 Cat 的父类
//animal.catchMouse();错误
//最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法然后调用
animal.eat();//猫吃鱼.. animal.run();//跑
animal.show();//hello,你好
animal.sleep();//睡
//多态的向下转型
Cat cat = (Cat) animal;
cat.catchMouse();//猫抓老鼠
//要求父类的引用必须指向的是当前目标类型的对象
Dog dog = (Dog)animal; //可以吗?不可以
System.out.println("ok~~");
}
}
- 属性没有重写之说!属性的值看编译类型
```java
public class PolyDetail02 {
public static void main(String[] args) {
} }//属性没有重写之说!属性的值看编译类型 Base base = new Sub();//向上转型 System.out.println(base.count);// ? 看编译类型 10 Sub sub = new Sub(); System.out.println(sub.count);//? 20
class Base { //父类 int count = 10;//属性 }
class Sub extends Base {//子类 int count = 20;//属性 }
5. `instanceOf` 比较操作符,**用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型**
```java
public class PolyDetail03 {
public static void main(String[] args) {
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类
AA aa = new BB();
System.out.println(aa instanceof AA);// true
System.out.println(aa instanceof BB);// true
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
//System.out.println(str instanceof AA);
System.out.println(str instanceof Object);//true
}
}
class AA {} //父类
class BB extends AA {}//子类
java 的动态绑定机制(重要)
Java 重要特性: 动态绑定机制
示例代码:
public class DynamicBinding {
public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
A a = new B();//向上转型
System.out.println(a.sum());//?40 -> 30
System.out.println(a.sum1());//?30-> 20
}
}
class A {//父类
public int i = 10;
//动态绑定机制:
public int sum() {//父类 sum()
return getI() + 10;//20 + 10
}
public int sum1() {//父类 sum1()
return i + 10;//10 + 10
}
public int getI() {//父类 getI
return i;
}
}
class B extends A {//子类
public int i = 20;
// public int sum() {
// return i + 20;
// }
public int getI() {//子类 getI()
return i;
}
// public int sum1() {
// return i + 10;
// }
}