Java中的多态

引言

  • 最近研究了一下java中的多态这一java特有的非常优秀的特性;
  • 多态增加了程序的灵活性和可扩展性,但是也对程序的安全性和稳定性提出了挑战;

多态的概念

  • 多态的定义:指允许不同类的对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用);
  • 多态的分类:编译时多态(方法的重载就是其具体实现),运行时多态(本文中的多态均指运行时多态);
  • 实现多态的技术是动态绑定(dynamic binding):是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法;
  • 多态的作用:消除类型之间的耦合关系;

多态存在的条件

  • 要有继承(包括接口的实现);
  • 要有重写;
  • 父类引用指向子类对象;

实例

  • 父类如下:
1
2
3
4
5
6
7
8
9
10
11
12
package test11;

public class BaseClass {
public int a = 6;
public void base(){
System.out.println("父类普通方法");
}

public void test(){
System.out.println("父类被覆盖方法");
}
}
  • 子类如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package test11;

public class SubClass extends BaseClass{
public int b = 8;
public int a = 8;
public void test(){
System.out.println("子类覆盖父类的test方法");
}

public void sub(){
System.out.println("子类普通方法");
}


public static void main(String[] args) {
BaseClass base = new BaseClass();
SubClass sub = new SubClass();
BaseClass bc = new SubClass();
//SubClass sb = new BaseClass(); //编译时报错,不能从父类到子类强制转换

System.out.println(base.a); //6
//System.out.println(base.b); //报错,因为BaseClass没有变量b
base.base(); //父类普通方法
base.test(); //父类被覆盖方法

System.out.println(sub.b); //8
System.out.println(sub.a); //8
sub.test(); //子类覆盖父类的test方法
sub.sub(); //子类普通方法
sub.base(); //父类普通方法

//System.out.println(bc.b); //编译时报错,编译时bc是BaseClass类,不含有变量b
System.out.println(bc.a); //6,因为变量没有多态的特性
bc.test(); //子类覆盖父类的test方法
//bc.sub(); //编译时报错,编译时bc是BaseClass类,不含有方法sub()
bc.base(); //父类普通方法

}

}
  • BaseClass base = new BaseClass();定义base为父类,可访问所有父类的变量和方法;
  • SubClass sub = new SubClass();定义为子类,优先访问子类中的变量和方法,如果没有,再从父类寻找;
  • 对于BaseClass bc = new SubClass();:
    • 编译时,系统首先new出来一个SubClass类的实例,系统自动将这个new出来的实例强制转换为BaseClass类型,并且赋给bc对象;
    • 运行时,bc对象名义上是BaseClass类型,实际上是SubClass类型,bc对象可访问且优先访问SubClass类中的方法,找不到的话再到它的父类BaseClass寻找;
    • 尽管bc对象在运行时是SubClass类型,bc对象在运行时是可以访问SubClass自己的方法的(比如sub()方法),但是由于bc对象在编译时是BaseClass类型,bc.sub()这一句话根本通不过编译,所以运行时bc对象实际上是不能访问sub()方法的;
    • 在编译时,base和bc对象都是BaseClass类型的对象,但是在运行时base仍为BaseClass类型,bc却是SubClass类型,这就出现了base和bc这两个编译时相同类型的变量,在运行时调用test()方法的结果却不一致的现象,就是多态;
    • 多态性只对方法有效,对于变量无效,所以访问bc对象的a变量时,输出父类的a变量而非子类的a变量值,这和java内部运行机制有关;
您的支持是对我最大的鼓励!