黑马程序员--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学习型技术博客、期待与您交流! ------------
相关文章推荐
- 黑马程序员--03.Java面向对象--05.【继承】【子父类中成员的特点】【子父类中构造函数的特点】
- 黑马程序员--03.Java面向对象--07.【多态】【instanceof操作符】
- 黑马程序员--03.Java面向对象--02.【static关键字】【main方法】【静态成员】
- 黑马程序员_Java基础_03面向对象思想(对象转型注意事项、多态、抽象类、final关键字等)
- java面向对象-多态中成员函数成员变量的特点
- 黑马程序员--03.Java面向对象--04.【对象初始化的过程】【对象调用成员的过程】
- 黑马程序员—java面向对象总结(3)—面向对象继承、多态特性
- 黑马程序员笔记——Java面向对象之多态
- 黑马程序员-博客 (3) 面向对象一之类和对象、成员变量和局部变量、继承、封装、多态
- 黑马程序员_java基础笔记(03)...面向对象
- 黑马程序员——Java基础---面向对象之多态
- 黑马程序员--------java面向对象 继承、接口、多态、Object类
- java学习日记_41:面向对象之抽象的引入、抽象的特点和抽象成员的特点
- 黑马程序员----java基础面向对象特点及封装
- 黑马程序员_java基础笔记(03)...面向对象
- 黑马程序员——Java面向对象封装继承多态
- 黑马程序员_java基础3-面向对象(二)多态、异常、包
- 黑马程序员--03.Java面向对象--03.【工具类】【静态代码块】
- 面向对象_多态中的成员访问特点
- 黑马程序员——Java基础---面向对象之多态抽象类接口