概念:方法或对象具有多种形态,这是面向对象的重要特征,多态是建立在封装和继承基础之上的。
多态具体体现在以下两个方面:
对象的多态体现在:一个对象的编译类型和运行类型可以不一样(其实也就是向上转型)。用代码来说可以写成:Base b = new Sub();
如果没有特殊说明,多态一般就是指对象的多态。
编译类型由声明该变量时使用的类型决定,即 = 左边的类型;运行类型由实际赋给该变量的对象决定,即 = 右边的类型。
对于对象的多态,有几点很关键:
向上转型的本质:父类的引用指向子类对象父类类型 引用名 = new 子类类型();
向上转型的调用规则:
代码示例(重点)
public class PolyTest {
public static void main(String[] args) {
Sub s =new Sub();
System.out.println(s.count);//20
System.out.println(s.num);//22
s.display();//20
//==========================重点==========================
Base b = s;//允许,向上转型
System.out.println((b == s));//true,两个引用都指向同一个对象(在堆中地址一样,内容一样)
//报错,向上转型时,不能访问子类中特有的成员变量及方法,因为在编译阶段,能调用哪些成员是由编译类型决定的。
//System.out.println(b.num);
System.out.println(b.count);//向上转型时,子类访问属性,从编译类型开始向上找,输出Base的count值10
System.out.println(b.s); //从编译类型Base开始向上找,输出Super的s值111
b.display(); //向上转型时,子类访问方法,从运行类型Sub开始向上找,调用Sub中的方法,输出20
//总结:访问属性时,向上转型的情况要从编译类型开始向上找。其他时候基本都是从子类开始想上找(存疑,暂时这么总结)
}
}
class Super{
int s = 111;
}
class Base extends Super{
int count = 10;
public void display(){
System.out.println(this.count);
}
}
class Sub extends Base{
int count = 20;
int num = 22;
int s = 222;
public void display(){
System.out.println(this.count);
}
}
总结:访问属性时,向上转型的情况要从编译类型开始向上找。其他时候基本都是从子类开始想上找(存疑,暂时这么总结)
向下转型后,我们就可以调用子类类型中的所有成员(方法和变量),其语法为:
子类类型 引用名 = (子类类型) 父类引用;
对于向下转型有以下注意事项:
代码示例(重点)
Sub c = (Sub) b;//向下转型
System.out.println(c.num);//向下转型后,我们就可以调用子类类型中的所有成员
Base bb = new Base();
//Sub cc = (Sub) bb;//运行后报错,只能强转父类的引用,不能强转父类的对象
Super ss = new Sub();
//==============================重点===========================================
//转型前的父类引用必须指向的是当前目标类型的对象
Base bbb = (Base) ss;//不报错,转型前的父类引用指向sub的对象,
// 而sub对象也是目标类型Base类的对象,即ss instanceof Base为true,
// 相当于向下转了一级
bbb.display();//运行类型还是Sub,执行Sub里的函数
System.out.println(bbb.count);//编译类型为Base,输出Base里的count
语法:对象 instance 类型
用于判断对象的运行类型是否为某类型或其子类,返回true/false
代码示例
class AA {} //父类
class BB extends AA {}//子类
public class Poly {
public static void main(String[] args) {
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
AA aa = new BB();
System.out.println(aa instanceof AA);//true
System.out.println(aa instanceof BB);//true,运行类型为AA子类
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
//System.out.println(str instanceof AA);//报错,字符串和AA无继承关系
System.out.println(str instanceof Object);//true
}
}