Java语言基础-面向对象三大特征(多态性)

1.理解多态性:

可以理解为一个事务的多种形态

2.何为多态性:

 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)

     可以直接应用在抽象类和接口上。

3.Java引用变量有两个类型:

             编译时类型和运行时类型。

             ①编译时类型由声明改变量时使用的类型决定。

             ②运行时类型由实际赋给该变量的对象决定。

             ③简称:编译时,看左边;运行时,看右边。

         >>若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)

         >>多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)

                                   “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

 Java语言基础-面向对象三大特征(多态性)正常方法的调用

Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();

  Java语言基础-面向对象三大特征(多态性)虚拟方法调用(多态情况下)

        子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。

 

Person e = new Student();
e.getInfo();         //调用Student类的getInfo()方法

Java语言基础-面向对象三大特征(多态性)编译时类型和运行时类型

      编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。    -------动态绑定

Java语言基础-面向对象三大特征(多态性)多态性的使用举例

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

	public void func(Animal animal) {
		animal.eat();
		animal.shout();
	}

	public void func(Dog dog) {
		// 如果没有多态性,只能一个一个写了,你声明什么类型,只能new这个类型的对象,进而显示出多态性的好处
		dog.eat();
		dog.shout();
	}

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

class Animal {

	public void eat() {
		System.out.println("动物:进食");
	}

	public void shout() {
		System.out.println("动物:叫");
	}

}

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

	public void shout() {
		System.out.println("汪汪汪");
	}
}

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

	public void shout() {
		System.out.println("喵喵喵");

	}
}

3.方法的重载与重写

  Java语言基础-面向对象三大特征(多态性)二者的定义细节:略

  Java语言基础-面向对象三大特征(多态性)从编译和运行的角度看:

     重载,是指允许存在多个同名方法,而这些方法的参数不同,编译器根据方法不同的参数表,对同名的方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定的了。Java重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。

所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;

而对于多态,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”;

引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就就不是多态。”

4.多态是编译时行为还是运行时行为?如何证明?

import java.util.Random;

//面试题:多态是编译时行为还是运行时行为?
//运行时行为
//证明如下:
class Animal {
	protected void eat() {
		System.out.println("animal eat food");
	}
}

class Cat extends Animal {
	protected void eat() {
		System.out.println("cat  eat fish");
	}
}

class Dog extends Animal {
	public void eat() {
		System.out.println("Dog eat bone");
	}
}

public class InterviewTest {

	public static Animal getInstance(int key) {
		switch (key) {
		case 0:
			return new Cat();
		case 1:
			return new Dog();
		default:
			return new Sheep();
		}
	}

	public static void main(String[] args) {
		int key = new Random().nextInt(3);

		System.out.println(key);

		Animal animal = getInstance(key);

		animal.eat();
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

上一篇:Java中的静态类和非静态类


下一篇:java多态 成员访问特点(父类引用指向子类对象)