目录
java多态
什么是多态?
多态,即多种形态、多种状态。编译期一种形态,运行期一种形态。
多态核心代码:父类型引用指向子类型对象
!!!多态的前提是:有继承关系 !!!
public class Test {
public static void main(String[] args){
//父类型引用指向子类型对象
Animal cat = new Cat();
Animal dog = new Dog();
//调用eat()
cat.eat();
dog.eat();
}
}
class Animal {
public void eat(){
System.out.println("动物都能吃东西");
}
}
//Cat继承Animal
class Cat extends Animal {
//重写eat()
public void eat() {
System.out.println("猫吃猫粮");
}
}
//Dog继承Animal
class Dog extends Animal {
//重写eat()
public void eat() {
System.out.println("狗吃狗粮");
}
}
运行的结果:
猫吃猫粮
狗吃狗粮
向上转型和向下转型
向上转型
子类型 —> 父类型
父类 父类对象=new 子类
向上转型可以自动转换
向下转型
父类型 —> 子类型
子类 子类对象=new 父类
向下转型需要加强制类型转换符前提:必须先发生向上转型
那么什么时候需要使用向下转型呢?
在多态中,父类型引用子类型对象时,如果需要访问子类特有的属性或方法时,需要向下转型,否则编译无法通过。
public class Test {
public static void main(String[] args){
//父类型引用指向子类型对象(自动类型转换)
Animal cat = new Cat();
Animal dog = new Dog();
//子类特有方法catchMouse()
cat.catchMouse();
}
}
class Animal {
public void eat(){
System.out.println("动物都能吃东西");
}
}
class Cat extends Animal {
//重写eat()
public void eat() {
System.out.println("猫吃猫粮");
}
public void catchMouse() {
System.out.print("猫抓老鼠");
}
}
class Dog extends Animal {
//重写eat()
public void eat() {
System.out.println("狗吃狗粮");
}
}
在编译期,编译器会检测到cat引用时Animal类型,编译器会到Animal.class中寻找catchMouse(),而Animal.class中并没有catchMouse(),所以编译器报错。
异常:
向上转型可能会出现异常:
在多态中,父类型引用指向子类型对象,在运行阶段会检测引用实际指向的对象,如果向上转型转换类型出错,并不会在编译期出现问题,但在运行期会抛出类型转换异常(java.lang.ClassCastException)
public class Test {
public static void main(String[] args){
//父类型引用指向子类型对象
Animal dog = new Dog();
Cat d = (Cat)dog;
}
class Animal {
public void eat(){
System.out.println("动物都能吃东西");
}
}
class Cat extends Animal {
//重写eat()
public void eat() {
System.out.println("猫吃猫粮");
}
public void catchMouse() {
System.out.print("猫抓老鼠");
}
}
class Dog extends Animal {
//重写eat()
public void eat() {
System.out.println("狗吃狗粮");
}
}
在编译期,Animal类型的dog引用经过转型后变成Cat类型并将对象的地址给Cat类型的d引用,编译器检测到d是Cat类型所以编译能通过,但是在程序运行期间,检测到d引用指向的对象实际是Dog类型,所以会抛出类型转换异常(java.lang.ClassCastException)
那么应该如何避免ClassCastException:
使用instanceof运算符判断引用指向对象的类型后再向下转型
instanceof运算符特点:
- instanceof用于检测引用指向的对象数据类型
- instanceof运算结果是true/false
- instanceof语法格式:引用 instanceof 数据类型
示例:
public class Test {
public static void main(String[] args){
Animal animal = new Cat();
if(animal instanceof Dog) {
Dog dog = (Dog)animal;
dog.eat();
}
if (animal instanceof Cat) {
Cat cat = (Cat)animal;
cat.eat();
}
}
}
class Animal {
public void eat() {
System.out.print("动物能进食");
}
}
class Dog extends Animal{
public void eat() {
System.out.print("狗吃狗粮");
}
}
class Cat extends Animal {
System.out.print("狗吃狗粮");
}
结果输出:狗吃狗粮
那么就会有人说了,多态这个共为什么要这么麻烦呢,有什么作用吗?
答案当然是有啦:
多态的目的就是降低程序耦合提高程序的扩展能力。