Java类——多态

一、多态性

\quadJava引用变量有两个类型:一个是编译时的类型,一个是运行时的类型,编译时的类型由声明该变量时的类型决定,运行时的类型由实际赋值给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现所谓的多态。
\quad先看一个父类Base和子类Sub的代码,根据其结果做进一步分析:

public class Base {
    public int book = 6;
    public void base() { System.out.println(1); }
    public void test() { System.out.println(2); }
}

public class Sub extends Base {
    // 重写父类的test方法
    public String book = "Java疯狂笔记";
    public void test() { System.out.println(3); }
    public void sub() { System.out.println(4); }
    public static void main(String[] args) {
        // 编译时类型和运行时类型不同,多态发生
        Base ploy = new Sub();
        System.out.println(ploy.book);  // 6
        ploy.test();  // 3
        ploy.base();  // 1
        // 不能调用ploy.sub();
    }
}

\quadBase ploy = new Sub();这句话表明对象ploy编译时类型是Base,而运行时是Sub。对于父类Base中没有被子类覆盖的方法,ploy得到的是父类的值,比如ploy.book=6, ploy.base=1;对于被覆盖的方法,实际执行的就是子类中覆盖掉父类方法,例如ploy.test=3是子类中被重写后的打印值。这就是多态!
\quadJava允许把一个子类对象直接赋给一个父类引用变量,无需任何类型转换,或者被称为向上转型(upcasting),向上转型由系统自动完成。
\quad当把一个子类对象直接赋给父类引用变量,例如上面的Base ploy = new Sub();对象ploy编译时类型是Base,而运行时是Sub。当运行时,其方法行为总是像子类的行为而不是父类的行为。这将出现相同类型的变量,执行同一个方法时出现不同的行为特征,这就是多态
\quad引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行其运行时类型所具有的方法。例如Object p = new Person()p只能调用Object类中的方法而不能调用Person类中的方法,但运行的时候首先看Person类中有没有此方法,有的话运行Person类中的方法,没有的话才运行Object类中的方法。
\quad与方法不同的是,对象的属性不具备多态性。如上面ploy变量输出book属性时并不是输出子类Sub的,而是输出父类的属性。

二、引用变量的强制类型转换

\quadJava程序中引用变量只能调用其编译时类型的方法,而不能调用其运行时类型的方法。如果要让这个引用变量来调用它运行时类型的方法吗,则必须把它强制类型转换为运行时类型,强制类型转换需要借助于类型转换运算符。
\quad强制类型转换语法很简单:(type) variable,这种用法可以将variable变量转换为一个type类型的变量。
\quad引用类型之间的转换只能把一个父类变量转换成子类类型,如果是两个没有任何继承关系的类型,则无法进行类型转换。即编译时类型为父类类型,运行时类型是子类类型。举个例子:

public class TestConversion {
    public static void main(String[] args)
    {
        Object obj = "Hello";
        // obj变量的编译类型是Object,是String类型的父类,可以进行强制类型转换
        String objstr = (String) obj;
        System.out.println(objstr);
        // obj2变量的编译类型是Object,是Integer类型的父类,可以进行强制类型转换
        // 但obj2运行时类型是Integer,所以下面程序会触发ClassCastException异常
        Object obj2 = new Integer(5);
        String obj2str = (String) obj2;
        System.out.println(obj2str);
    }
}

在这里插入图片描述
\quad考虑到进行强制类型转换时可能出现异常,因此进行强制类型转换之前应先通过instanceof运算符来判断是否可以成功转换。例如可将代码改为:

 if(obj2 instanceof String) 
 {
     String obj2str = (String) obj2;
     System.out.println(obj2str);
 }

三、instanceof运算符

\quadinstanceof运算符使用格式:引用类型变量 instanceof 类;
用于判断前面的对象是否是后面的类,或是其子类的实例。如果是则返回true,否则返回false

public class TestInstanceof {
    public static void main(String[] args)
    {
        Object str = "Hello";
        System.out.println(str instanceof String);  // true
        System.out.println(str instanceof Object);  // true
        System.out.println(str instanceof Math);    // false
        // 下面程序无法编译,运算符前面的数的编译类型必须与后面的类相同或是后面类的父类
        // System.out.println((String)str instanceof Math);
    }
}
发布了222 篇原创文章 · 获赞 99 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章