Java 多态性

------------恢复内容开始------------

------------恢复内容开始------------

1.理解多态性:多态是一个事务的多种形态。

2.何为多态性?

  对象的多态性:一个父类的引用指向子类的对象。

  这句话太抽象了,用汉语结构拆分开就是 “引用  指向 对象”,这也还是很抽象

  直接看个例子

  先写一个Person类 ,定义方法eat & walk

package Poly;

public class Person {
    String name;
    int id;
    public void eat(){
        System.out.println("恰饭");
    }

    public void walk(){
        System.out.println("walking");
    }
}

  再用继承一个Man类 和  Women类

package Poly;

public class Man extends Person{
    public void eat(){
        System.out.println("man 恰饭");
    }

    public void walk(){
        System.out.println("man walking");
    }

    public void EarnMoney(){
        System.out.println("earning..");
    }
}
package Poly;

public class Women extends Person{
    public void eat(){
        System.out.println("women 恰饭");
    }

    public void walk(){
        System.out.println("women walking");
    }

    public void shop(){
        System.out.println("shopping...");
    }
}

编写一个Test测试类,一般的我们引用 和 对象是相一致的就如下面example1一样,而多态就是example2

package Poly;

public class PolyTest {
    public static void main(String[] args) {
        //example1
        Person p1 = new Person();
        p1.eat();
        p1.walk();

        //example2
        Person p2 = new Man();
        //1
        p2.walk();
        //2
        p2.eat();
        //3
       // p2.EarnMoney();
    }
}

运行结果如下:

 

 example1的结果不用解释

可以看到example2的结果是子类重写的方法的运行结果

并且3是无法编译通过的,原因是Person中并没有EarnMoney这个方法。

由此我们可以得出 多态必须基于继承 & 重写上,

并且编译时,方法是父类中定义的,而结果确是子类重写方法运行的。 即“编译时看左,执行时看右”。这便是虚拟方法调用

由此可以理解多态性的前提:①继承 ②方法重写

 

3.为什么要有多态性?

看了2之后还是很抽象,只是知道了多态性是怎么回事,它的意义在哪?

看下面这个例子

定义Animal类 , 子类为Dog & Cat

class Animal{
    public void shout(){
        System.out.println("aaaa");
    }

    public void eat(){
        System.out.println("eating...");
    }
}

class Dog extends Animal{
    public void shout(){
        System.out.println("汪!汪!汪!");
    }

    public void eat(){
        System.out.println("吃骨头");
    }
}

class Cat extends Animal{
    public void shout(){
        System.out.println("miao miao miao");
    }

    public void eat(){
        System.out.println("吃猫粮");
    }
}

很明显,这符合多态性的两个前提 : 继承 & 方法重写

我们写一个方法测试这两个子类的方法

 public static void main(String[] args) {
        PolyTest test = new PolyTest();
        test.func(new Dog());
        test.func(new Cat());
    }

    public void func(Animal animal){//Animal animal = new Dog();
                                    //Animal animal = new Cat();
        animal.eat();
        animal.shout();
    }

在调用func的时候 ,很自然的会这么写:

test.func(new Dog());
test.func(new Cat());
实质上 在背后,相当于执行了
Animal animal = new Dog();
Animal animal = new Cat();
这不就是多态吗?
如果没有多态,我们只能这样写
public void func1(Dog dog){
        dog.eat();
        dog.shout();
    }

    public void func2(Cat cat){
        cat.eat();
        cat.shout();
    }

明显的,多态减少了代码的冗余,实质上,我们在编写代码的过程中,无意中就使用了多态

例如: 在JDBC中 ,我们总是会 Connection conn = new MySQLConnection(); .. 这也是多态

 

值得指出的是属性是没有多态性的

 

4、多态性是运行时行为

经典的例子是在main方法中写一个随机数 随机选择子类对象,多次运行会得到不同的结果。

 

5、内存空间问题

有了对象的多态性以后,内存中(堆)实际上是加载了子类的所有属性和方法的,但是由于声明是父类类型,所以子类的特有的属性和方法是不能被调用的。

如何才能实现调用呢?

将父类强制类型转换为子类 也叫向下转型

相反的,子类转换为父类称为向上转型。 有点眼熟?。 一般地,我们直接称为“多态”

在同级子类中,强制类型转换有可能会出现问题。

 

6、instanceof关键字使用

a instanceof A 判断对象a是否为类A的实例,是返回true,否则否则返回false

使用此关键字可以判断,避免向下转型时出现ClassCastExecption异常。

 

------------恢复内容结束------------

posted @ 2022-01-05 14:10  Rook1e  阅读(68)  评论(0)    收藏  举报