Java笔记:多态

多态是继封装、继承之后面向对象的第三大特性。
多态也即是同一行为多个不同的表现形式

前提

  1. 继承或者实现
  2. 方法的重写
  3. 父类引用指向子类对象

多态体现的格式

父类类型 变量名 = new 子类类型();
变量名.方法名();

父类类型:即子类对象继承的父类类型或者实现的接口类型

代码举例:

Fu f = new Zi();
f.method();

当使用多态的方式来调用方式时,首先会检查父类中是否含有该方法,若没有就会产生编译错误;若有,就会执行子类覆盖重写的方法
代码举例:
定义父类:

public abstract class Animal{
    public abstract void eat();
}

定义子类

public class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
}

public class Dog extends Animal{
    public void eat(){
        System.out.println("吃肉骨头");
    }
}

定义测试类

public class Test{
    public static void main(String[] args){
        //多态形式创建对象
        Animal cat = new Cat();
        //调用Cat类中eat()方法,输出吃鱼
        cat.eat();
        Animal dog = new Dog();
        //调用Dog类中eat()方法,输出吃肉骨头
        dog.eat();      
    }
}

多态优点

在实际开发中,使用父类类型作为方法的形式参数,然后传递子类对象给方法,供方法调用能够体现出多态的扩展性和便利性,代码举例
定义父类

public abstract class Animal{
    public abstract void eat();
}

定义子类

public class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
}

public class Dog extends Animal{
    public void eat(){
        System.out.println("吃肉骨头");
    }
}

定义测试类

public class Test{
    public static void main(String[] args){
        Cat cat = new Cat();
        Dog dog = new Dog();
        showCatEat(cat);
        showDogEat(dog);
        //以上两个方法均可以被showAnimalEat(Animal a)所取代,同时机型效果一致
        showAnimalEat(cat);
        showAnimalEat(dog);
    }
    public static void showCatEat(Cat cat){
        cat.eat();
    }
    public static void showDogEat(Dog dog){
        dog.eat();
    }
    public static void showAnimalEat(Animal a){
        a.eat();
    }
}

在多态特性的支持下,showAnimalEat方法中的参数可以接受Animal的子类对象,而当方法执行时,会执行子类覆盖重写的方法,所以即便此后出现更多子类,showAnimalEat也可以完全替代

多态使得程序编写更加简单,并且获得良好的扩展

引用类型转换

多态的转型可分为向上转型和向下转型两种

  • 向上转型:子类类型向父类类型转化的过程,此过程一般时默认的

    当父类引用指向一个子类对象时,便是向上转型
    格式

父类类型 变量名 = new 子类类型();
如:Animal a = new Cat();
  • 向下转型:父类类型向子类类型转化的过程必须强制进行

    一个已经向上转型的子类对象,将父类引用转化为子类引用,可以用强制类型转化的格式,即是向下转型
    格式

子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c = (Cat) a;

为什么要进行转型
当使用多态方式调用方法时,首先会检查父类中是否含有该方法,若没有,则会产生编译错误。也即是说,无法调用子类特有的而父类不存在的方法,若果想要调用子类特有方法,则必须向下转型

定义类

public abstract class Animal{
    public abstract void eat();
}

public class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
    public void catchMouse(){
        System.out.println("抓老鼠");
    }
}

public class Dog extends Animal{
    public void eat(){
        System.out.println("吃骨头");
    }
    public void watchHouse(){
        System.out.println("看家");
    }
}

定义测试类

public class Test{
    public static void main(String[] args){
        Animal a = new Cat();  //向上转型
        a.eat();   //调用了Cat中的eat

        Cat c = (Cat) a;  //向下转型
        c.catchMouse();  //调用了Cat中的catchMouse
    }
}

转型异常

public class Test{
    public static void main(String[] args){
        Animal a = new Cat();  //向上转型
        a.eat();   //调用了Cat中的eat

        Dog d = (Dog) a;  //向下转型
        d.watchHouse();  //运行报错
    }
}

这段代码能够通过编译,但是运行时会爆出ClassCastException,类型转换异常,因为创建的是Cat类型对象不能转化为没有继承关系的Dog对象,不符合类型转换定义
为了避免ClassCastException,可以通过instanceof检验

变量名 instanceof 数据类型
如果变量属于该类型,返回true
反之返回false

所以在转换前最好做一个判断

public class Test{
    public static void main(String[] args){
        Animal a = new Cat();  //向上转型
        a.eat();   //调用了Cat中的eat

        if (a instanceof Cat){
            Cat c = (Cat) a;
            c.catchMouse();
        }else if (a instanceof Dog){
            Dog d = (Dog) a;
            d.watchHouse();
        }
    }
}

附一个多态面试题

class A {  
     public String show(D obj){  
            return ("A and D");  
     }   
     public String show(A obj){  
            return ("A and A");  
     }   
}   
class B extends A{  

     public String show(B obj){  
            return ("B and B");  
     }  
     public String show(A obj){  
            return ("B and A");  
     }   
}  
class C extends B{}   
class D extends B{}

class  DynamicTest
{   
    public static void main(String[] args){

    A a1 = new A();  
    A a2 = new B();  
    B b = new B();  
    C c = new C();   
    D d = new D();   
    System.out.println(a1.show(b));  
    System.out.println(a1.show(c));  
    System.out.println(a1.show(d));    

    System.out.println(a2.show(b));  


    System.out.println(a2.show(c));            



    System.out.println(a2.show(d));  


    System.out.println(b.show(b));   


    System.out.println(b.show(c));   


    System.out.println(b.show(d));   

    }
}

猜你喜欢

转载自blog.csdn.net/FallingSkies/article/details/81665307