1>Java引用变量有两个类型,一个是编译时类型,一个是运行时类型。
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
如果编译时类型和运行时类型不一致时,就可能出现所谓的多态。
2>测试
2.1>基类
package com.demo.poly;
public class BaseClass {
public int book=6;
public void base(){
System.out.println("---父类的普通方法---base()");
}
public void test(){
System.out.println("---父类的普通方法---test()");
}
}
2.2>子类
package com.demo.poly;
public class SubClass extends BaseClass {
//重新定义一个book实例变量隐藏父类的book实例变量
public String book="JAVA SE";
public void sub(){
System.out.println("***子类的普通方法***sub()");
}
public void test(){
System.out.println("***子类的普通方法***test()");
}
}
2.3>测试类
package com.demo.poly;
public class PolyDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//编译时类型和运行时类型不一样,因此有可能会发生多态
BaseClass bc= new SubClass();
bc.base();
/*
* 引用变量 bc 的编译时类型是BaseClass,而运行时类型是SubClass
* 当调用该引用 变量的test()方法时(BaseClass 类中定义了该方法,子类SubClass 覆盖(Override)了父类的方法),
* 实际执行的时SubClass类中的覆盖了后的test()方法,这就可能出现多态了。
*
* 如下所示的调用,执行SubClass中具有的方法test()
*/
bc.test();
/* 引用变量 bc 的编译时类型是BaseClass,而运行时类型是SubClass
* 当调用子类的方法sub()时,会出现如下编译错误:
* The method sub() is undefined for the type BaseClass.
* 引用变量在编译阶段只能调用其编译时类型所具有的方法,但是运行时则会执行其运行时类型所具有的方法,
* 所以编写Java代码时,引用变量只能调用声明该变量时所用类里包含的方法,而不能调用其运行时类型类里所包含的方法。
* */
//bc.sub();
/*
* 可以通过 强制类型转换实现
* 即调用引用变量的运行时类型所具有的方法,
* 引用类型之间的类型转换只能在具有继承关系的两个类型之间进行,
* 如果两个没有任何继承关系的类型,则无法进行类型转换,将在编译时出现错误。
*
* 如果试图把一个父类型实例转换成子类类型,则这个父类实例必须是子类类型(即编译时类型是父类型,运行时是子类类型)才行,
* 否则将会出现ClassCastException异常。
* */
SubClass sc;
if(bc instanceof SubClass){
sc=(SubClass)bc;
sc.sub();
}else {
System.out.println("----------Error");
}
/*
* 对象的实例变量则不具备多态性
* 通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,
* 而不是它运行时类型所定义的成员变量
* */
System.out.println("----book:"+bc.book);//6,而不是“JAVA SE”
}
}
运行结果如下:
---父类的普通方法---base()
***子类的普通方法***test()
***子类的普通方法***sub()
----book:6