
这一节复习java面向对象的特征多态性,主要讲解对象的上转型与下转型以及 instanceof 关键字的使用!
理解多态性
可以理解为一个事物的多种形态!
何为多态性
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用),即对象的上转型!
多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译看左边;运行看右边。
多态性的使用前提:①类的继承关系②方法的重写
对象的多态性:只适用于方法,不适用于属性!(属性无法被重写,编译和运行都看左边)
总结:
子类的上转型对象可以调用:
子类的上转型对象不可以调用:
如果父类要调用子类的特有方法就得将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,此时必须进行强制类型转换。

这个案例是向上转型与向下转型的Demo
package 多态;
public class Demo {
public static void main(String[] args) {
Animal a = new Cat(); // 向上转型
System.out.println("-------------向上转型-------------");
a.eat(); // 调用的是 Cat 中重写的 eat 方法
System.out.println(a.name); //输出的父类Animal的name,子类新增的属性无法被调用
a.sleep(); // 调用的是子类继承父类的方法
//a.work(); 错误,子类新增的方法无法被调用
// 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但由于变量类型的申明为父类类型,
// 导致编译时,只能调用父类中申明的属性和方法,子类特有的属性和方法不能被调用
// 如何才能调用子类特有的属性和方法?
// 向下转型,使用强制类型转换
System.out.println("-------------向下转型-------------");
Cat c = (Cat) a;
c.work();
}
}
class Animal {
String name = "动物";
void eat(){
System.out.println("吃肉");
};
void sleep(){
System.out.println("睡觉");
}
}
class Cat extends Animal {
String name = "cat";
@Override
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}

先来看这样的一个情景
package 多态;
public class Demo {
public static void main(String[] args) {
Animal a = new Cat(); // 向上转型
// 使用强转时,可能出现ClassCastException异常
// 这里dog类和cat类无关,向下转型只能转换为Cat类型
Dog g = (Dog) a;
g.work();
}
}
class Animal {
String name = "动物";
void eat(){
System.out.println("吃肉");
};
void sleep(){
System.out.println("睡觉");
}
}
class Cat extends Animal {
String name = "cat";
@Override
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
String name = "dog";
@Override
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}

如图,出现了类型转换异常!
由此,我们引出一个关键字 instanceof 来避免这个问题
可以用 instanceof 判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。instanceof 的语法格式为:
对象 instanceof 类(或接口)
它的返回值是布尔型的,或真(true)、或假(false)。
使用情境:为了避免在向下转型时出现 ClassCastException 的异常
先进行 instanceof 的判断,一旦返回 true ,就进行向下转型。如果返回 false,不进行向下转型。
package 多态;
public class Demo {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat) a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog d = (Dog) a;
d.work();
}
}
}
class Animal {
String name = "动物";
void eat(){
System.out.println("吃肉");
};
void sleep(){
System.out.println("睡觉");
}
}
class Cat extends Animal {
String name = "cat";
@Override
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
String name = "dog";
@Override
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}

//向下转型的问题
// 问题一:编译通过,运行不通过
//例一:
Animal c = new Cat();
Dog d = (Dog) c;
//例二:
Animal a = new Animal();
Cat c = (Cat) a;
// 问题二:编译不通过,运行不通过
//例:
Cat c = new Animal();
// 问题三:编译通过,运行通过
//例:
Object obj = new Cat();
Animal a = (Animal) obj;
问题三是正确的写法,我们知道Object类是所有类的父类,因此可以上转型为Object类型,向下转型为Cat类型,而Animal类是Cat类的父类,自然可以向下转型为Animal类型!

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。
🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门