Java面向对象有三大特点,封装、继承、多态。

Java中多态的存在必须要满足三个条件:

1.要有继承

2.要有实例方法的重写 (注意只有实例方法才有多态行为,其它方法没有。)

3.要有父类的引用指向子类的对象 ,简单举例就是  Parent p = new Child();

使用多态调用方法时,按照下列方法进行:

1.首先检查父类中是否有该方法,如果没有该方法则直接报错。

2.如果有,再去检查子类中的同名方法。

3.如果子类中的方法是对父类中方法的重写(即函数名,返回类型,参数列表完全一致)则调用子类中的方法,否则调用父类中的方法。

class Animal {
    public void enjoy() {
        run();
    }
    public static void run() {
        System.out.println("animal is running!");
    }
}

class Dog extends Animal {
    public void enjoy() {
        System.out.println("dog is enjoying");
    }
    public static void run() {
        System.out.println("dog is running");
    }
}

public class Test {
    public static void main(String args[]) {
        Animal a = new Dog();
        a.enjoy();
        a.run();

    }

结合具体实例来说明:

 1 class Animal {
 2     public void enjoy() {
 3         run();
 4     }
 5     public static void run() {
 6         System.out.println("animal is running!");
 7     }
 8 }
 9 
10 class Dog extends Animal {
11     public void enjoy() {
12         System.out.println("dog is enjoying");
13     }
14     public static void run() {
15         System.out.println("dog is running");
16     }
17 }
18 
19 public class Test {
20     public static void main(String args[]) {
21         Animal a = new Dog();
22         a.enjoy();
23         a.run();
24 
25     }
26 }
View Code

 运行结果如图:

                      

此程序中存在多态,当调用a.enjoy()方法时,首先去父类Animal中检查是否有enjoy()方法,有则继续去子类Dog中调用enjoy()方法,因此第一行输出的是"dog is enjoying"。

当调用a.run()方法的时候,由于run()方法是static类型,不能被子类重写,因此调用的时候仍然是调用的父类的run()方法。

再看一个例子:

class Animal {
    public void enjoy() {
        run();
    }
    public void run() {
        System.out.println("animal is running!");
    }
}

class Dog extends Animal {
    public void enjoy(int i) {
        System.out.println("dog is enjoying");
    }
    public void run() {
        System.out.println("dog is running");
    }
}

public class Test {
    public static void main(String args[]) {
        Animal a = new Dog();
        a.enjoy();
    }
}
View Code

 

运行结果如图:

那么我们的问题来了,,,, 当调用a.enjoy()方法时,为什么没有去调用子类Dog中的enjoy()方法呢?如果仔细对照多态存在的三个条件你会发现,enjoy()方法并没有构成多态。因为它没有对父类的方法进行重写!!!在此处是进行了方法的重载。因此此处实际上时先调用了父类的enjoy()方法,进一步调用了子类的run()方法(因为run()方法有重写构成了多态)。父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;

4.父类引用指向子类对象,实际上是看到的作为父类那部分所拥有的属性和方法,如果想要调用子类中有而父类中没有的方法,则需要进行强制类型转换(向下的类型转换)。再看上述代码,如果a想要调用子类中的enjoy()方法,则代码可以修改如下:

class Animal {
    public void enjoy() {
        run();
    }
    public void run() {
        System.out.println("animal is running!");
    }
}

class Dog extends Animal {
    public void enjoy(int i) {
        System.out.println("dog is enjoying");
    }
    public void run() {
        System.out.println("dog is running");
    }
}

public class Test {
    public static void main(String args[]) {
        Animal a = new Dog();
        Dog b = (Dog)a;
        b.enjoy(33);
    
View Code

 

运行结果如图:

值得注意的是,此处是不能通过a.enjoy(33)来调用子类方法的,原因参照1.父类中没有该方法,所以编译会报错。

posted on 2014-11-06 19:42  beyond_Acm  阅读(226)  评论(0编辑  收藏  举报