JAVA的多态

前言

断断续续看《JAVA核心技术》有一个多星期的时间了,发现多态是面向对象三要素里不太好理解的概念,这里记录一下自己的学习。(ps:我发现自己之前对多态的理解太片面了,应该只是了解了重写,幸亏面试没考到,万幸)

java多态实现

java的多态和c++一样,是通过动态绑定或者说运行时绑定来实现的。当调用某一个对象引用的方法时,因为编译器并不知道这个引用到底指向的是变量声明时说明的类型对象,还是该类型子类的对象。因此编译器无法为这次调用绑定到具体的某个方法。只有通过java中运行时类型识别(RTT)在运行时绑定到具体的方法

方法的重写overriding和方法的重载overloading是java多态的不同表现。重写overriding是父类和子类之间多态性的一种表现,重载overloading是一个类中多态性的表现。

给出一个具体例子:

class People {
	public String toString() {
		return "I am a people!";
	}

	public void eat() {
	};

	public void speak() {
	};
}

class Boy extends People {
	public String toString() {
		return "I am a boy!";
	}

	public void fight() {
	};

	public void speak() {
	};
}

class Girl extends People {
	public String toString() {
		return "I am a girl!";
	}

	public void sing() {
	};

	public void speak() {
	};
}

public class TestToString {
	public static void main(String args[]) {
		People p = new Girl();
		System.out.println(p.toString());
	}
}


运行结果是:

I am a girl!

p是People的一个引用,但是在运行时因为是Girl对象,所以还是调用了Girl的toString方法


深入理解java多态

声明,这里借鉴了其他同学的例子,原文链接: http://blog.csdn.net/thinkghoster/article/details/2307001

测试题目


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 {
	
}

public class Main {
	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)); // 1
		System.out.println(a1.show(c)); // 2
		System.out.println(a1.show(d)); // 3
		System.out.println(a2.show(b)); // 4
		System.out.println(a2.show(c)); // 5
		System.out.println(a2.show(d)); // 6
		System.out.println(b.show(b));  // 7
		System.out.println(b.show(c));  // 8
		System.out.println(b.show(d));  // 9
	}
}


答案


A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D


解析

我开始做这道题目,4、5、6、9全部做错了,原因就是没能很好的理解java的多态性,这里说明一下

首先,要深刻的理解重写和重载,重写不仅仅包括了函数名称相同,也包括参数类型和返回值类型

其次,深刻理解这句话“ 当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类重写的方法

然后,我们在来分析一下这几道题目

问题:你认为B重写了父类A的show方法了吗?如果重写了,重写了几个?

答案:重写了,重写了一个,也就是public String show(A obj),为什么public String show(B obj)不算重写父类方法呢,很简单,因为参数类型不同

举例分析

看了上面的分析,我们也来分析两个例子:

一、a2.show(b):

a2是一个引用变量,类型为A,b是B的一个实例。首先,在类A中找show(B obj),没有找到。于是到A的超类中找,而A没有超类,因此转向了A.this((super)B),(super)B为A,因此在A中找到了show(A obj)的方法,但是由于a2引用的类B的一个对象,B重写了A的show(A obj)方法,因此最终锁定到类B的show(A obj),输出为“B and A”

二、a2.show(c):
a2是一个引用变量,类型为A,b是B的一个实例。首先,在类A中找show(C obj),没有找到。于是到A的超类中找,而A没有超类,因此转向了A.this((super)C),(super)C为B,到这里为止,这个a2.show(c)变成了a2.show(b)的问题,而a2.show(b)上面已经分析了是输出"B and A ",因此这里也是输出“B and A”



你可能感兴趣的:(JAVA的多态)