您的位置:首页 > 职场人生

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

2013-07-20 16:13 645 查看

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学习型技术博客、期待与您交流! ------------
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐