Java引用变量有两种类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量式使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可以能出现所谓的多态(polymorphism).
class BaseClass{
public int book=6;
public void base(){
System.out.println("父类的普通方法");
}
public void test(){
System.out.println("父类的被覆盖的方法");
}
}
public class SubClass extends BaseClass {
//重新定义一个book实例变量隐藏父类的book实例变量
public String book="轻量级Java ee企业应用实践";
public void test(){
System.out.println("子类覆盖父类的方法");
}
public static void main(String[] args){
//下面编译时类型和运行时类型一致,因此不存在多态
BaseClass bc=new BaseClass();
System.out.println(bc.book);
bc.base();
bc.test();
//下面编译时类型和运行时类型一致,因此不存在多态
SubClass sc=new SubClass();
System.out.println(sc.book);
sc.base();
sc.test();
//下面编译时类型和运行时类型不一致,因此存在多态
BaseClass pbs=new SubClass();
System.out.println(pbs.book);//访问的是父类对象的实例变量
pbs.base();//调用执行从父类继承到的base()方法
pbs.test();//调用执行当前类的test()方法
//psb.sub();//编译出错,因为psb的编译类型是BaseClass类,并没有提供sub()方法
}
}
子类其实是一种特殊的父类,因此Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换,或者被称为向上转型,向上转型由系统自动完成。
当把一个子类对象直接赋给父类引用变量时,当运行时调用该引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就可能出现:相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态。
与方法不同的是,对象的实例变量则不具备多态性。
引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法。
通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时所定义的成员变量。
引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法。
强制类型转换需要借助于类型转换运算符。类型转换运算符的用法:(type)variable
注意:1、基本类型之间的转换只能在数值类型之间进行;2、引用类型之间的转换只能在具有继承关系的两个类型之间进行。
进行类型转换之前应先通过instanceof运算符来判断是否可以成功转换,从而避免出现ClassCastException异常,这样可以保证程序更加健壮。
instanceof运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类,它用于判断前面的对象是否是后面的类,或者子类、实现类的实例。如果是,则返回true,否则返回false。