黑马程序员--03.Java面向对象--08.【多态中成员的特点】

来源:互联网 发布:袜子在淘宝哪个类目 编辑:程序博客网 时间:2024/04/27 13:35

Java面向对象--8

      多态中成员的特点

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

1.    多态中成员的特点

1). 多态中重名非静态成员方法的特点

父类引用指向子类对象的时候,多态中成员函数的特点:

[1]. 编译通过的关键

       {1}.查看父类引用变量所属的类是否调用该类存在的方法

{2}. 如果调用了该类不存在的方法编译不能通过

[2]. 运行期间

       JVM运行子类对象自身的方法。

【简单归纳】静态成员函数多态调用时候,编译能否通过看左边运行结果看右边

e.g.1

class Fu{    void method1(){        System.out.println("fu method1");    }       void method2(){        System.out.println("fu method2");    }} class Zi extends Fu{    void method1() {        System.out.println("zi method1");    }     void method3() {        System.out.println("zi method3");    }}
 

Zi z =new Zi();

z.method1();    //运行自身的method1

z.method2();    //从父类继承而来,运行父类的method2

z.method3();    //运行自身的method3

打印结果:


e.g.2 如果调用改成以下:

Fu f =new Zi();

f.method1();

f.method2();

f.method3();

这样编译会报错:因为编译的时候,javac不会考虑行与行之间的关系,仅仅检查每一行的语法是否正确。编译的时候,Fu f =new Zi();符合向上类型转换,正确。

但是赋值语句右边的new Zi()是运行时候才执行的,所以编译期间,无法知道将其赋给父类引用的时候,父类引用是否真的能找到父类中没有的方法method3。所以f.method3();产生编译错误。

2). 多态中重名非成员变量的特点

【结论】多态中,子父类中出现同名的成员变量时候,无论是编译还是运行,都参考的是赋值左边(也就是引用变量所属的类)

【面试题目】

class Fu{    int num =5;    void method1(){    }    void method2(){           }}class Zi extends Fu{    int num =8;    void method1(){    }       void method2(){           }}

测试类:

class DuotaiDemo{

    public static void main(String[] args) {

        Fuf =new Zi();

        System.out.println(f.num);

        Ziz =new Zi();

        System.out.println(z.num);

    }

}

打印结果是什么?

根据上面的结论:多态中父子类出现同名变量的时候,无论是编译还是运行的时候,都是以等式左边的父类引用为主,不会出现覆盖的情况。

3). 多态中重名静态成员方法的特点

这种情况主要是面试的时候使用。

class Fu{    static void method4(){        System.out.println("Fu static method4");    }} class Zi extends Fu{    static void method4(){        System.out.println("Zi static method4");    }} class DuotaiDemo{    public static void main(String[] args) {        Fuf =new Zi();        Zi z =new Zi();        f.method4();        z.method4();    }}


这里面要重点看得是:

f.method4();    打印结果:Fu static method4

z.method4();    打印结果:Zi static method4


【误区】认为子类和父类的同名静态函数会发生覆盖X不会发生覆盖!!

(1). 当子类父类中同名的静态函数的处理方式

[1]. 结论通过MyEclipse可以验证出来,子类父类同名静态方法是不会发生覆盖的

[2]. 知识点1静态成员的调用方式有两种

{1}. 类名.静态成员 (根本调用方式)

{2}. 类的引用变量.静态成员 (另一种调用方式)

方式{1}是最根本的方式。因为静态成员加载是通过类名加载

方式{2}是要查找到引用变量的类型,再通过找到的类名进行加载。

[3]. 知识点2非静态成员的调用方式仅仅有一种,那就是:通过对象引用.来调用

       但是注意:运行的时候对象引用去调用这个方法的时候,真正的还是通过对象引用这个引用指向的真正堆内存中对象,再由这个对象去调用本身存在的方法

所以:f.method1();打印的结果是 Zi method1. //因为f真正指向的是Zi类的内存对象

     f.method4();打印的结果是 Fu staticmethod4

     原因:f.method4();运行的时候,会去找f对应的类是Fu,由Fu来调用method4()。

    所以相当于:Fu.method4() 所以打印结果是 Fu staticmethod4

[4]. 【绝招】程序中涉及到静态的调用的时候,一定要检查一下相应的静态调用是不是通过最根本的类名.静态成员加载的。如果是,继续分析。

****如果不是,首先应该把这种静态成员的调用改成最根本的静态成员调用的方式:类名.静态成员。****

然后再进行分析

4). 子父类中重名的成员的结论

记住即可。

应用场合:在父类的引用指向子类的对象的时候会用到以下结论

[1]. 子类父类出现同名的成员变量的时候,无论是否是静态成员还是非静态成员编译运行看得全部是引用所在的类

       非静态成员变量因为内存存储的原因,不会发生覆盖

       静态成员变量根本就不会存在覆盖一说

[2]. 子类父类出现同名的成员函数的时候,静态非静态调用有区别:

{1}. 静态方法由于不存在覆盖的概念,所以,编译、运行仅仅看父类引用所在的类的类型

{2}. 静态方法是:编译时候看父类引用所在的类型运行时候看引用指向的对象的类型

静态成员使用时候的绝招一律把引用.静态成员的调用方式改成类名.静态成员的方式】

静态成员(变量+方法)+非静态成员变量父类引用类型非静态成员方法编译引用类型,运行子类对象类型】

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

 

原创粉丝点击