什么是属性的隐藏
在父子类中,是可以出现同名的成员变量的,那么如果创建子类对象,然后访问该同名成员变量,访问到的结果是子类中该成员变量的取值。父子类成员变量存储在子类对象中的不同区域,由于某种访问机制,属性被隐藏了,这种现象称之为”属性的隐藏“。
“对象名.成员变量“的访问机制
存在继承后,由于父子类的关系,就有了三种创建对象的方式:
- 子类引用指向子类对象
- 父类引用指向父类对象
- 父类引用指向子类对象(子类”is-a“父类)
从以下两个角度阐述“对象名.成员变量“的访问机制:
访问的范围
-
子类引用指向子类对象
访问范围是“父类+子类”
-
父类引用指向父类对象
访问范围是“父类”
-
父类引用指向子类对象
在不做强制类型转换的情况下,访问范围只有“父类”
小结:“对象名.成员变量”的访问范围要看引用的数据类型:
- 如果引用是父类类型,那么访问范围是“父”
- 如果引用是子类类型,那么访问范围是“父+子”
在Java中,“对象名.成员变量”访问成员变量的范围是编译器决定的,是一个编译上的概念。
编译器在检索一个引用是否能够访问到某个成员变量时,存在如下检索机制:
- 首先,编译器会从引用的数据类型的那个类中,去查找该成员变量。如果找到了,就直接认为它可以访问(有权限才可以真正访问)
- 如果从引用的数据类型中没有找到,那么就去引用类型的父类中找,直到找到Object类,如果全程都没有该成员变量,那么就会编译报错。
总的来说,在Java中,访问变量是可以往上查找引用类型的父类的,但不能往下查找子类。
访问的结果
-
子类引用指向子类对象
体现出子类中成员变量的取值。如果访问的是父类独有的成员变量,那么就体现出父类中的成员变量的取值。
-
父类引用指向父类对象
体现出父类中成员变量的取值。父类不能访问子类。
-
父类引用指向子类对象
如果访问同名成员变量,访问结果是父类中的取值。
小结:“对象名.成员变量”的访问结果是由引用的数据类型来决定的,引用是什么类型,该成员变量的结果就是该类中的取值。
- 如果引用是父类类型,那么它的访问结果一定也是父类中的结果。
- 如果引用是子类类型,那么它的访问结果一定也是子类中的结果。
总结
“对象名.成员变量”访问成员变量的范围和结果,都是根据引用数据类型来决定的,无需考虑是何种对象。
注意事项
- 父子类中的同名成员变量它们各自有存储的区域。父类的同名成员变量被子类的同名成员变量隐藏了,但我们仍然可以通过父类中的Getter方法,或者通过super关键字去访问到父类中的同名成员变量,当然它们都受访问权限限制。
- 对于静态成员变量,看起来可以用子类类名使用父类的静态成员变量,但实际上是共用了父类的静态成员变量。静态成员属于类,不是继承,也不考虑继承。如果子类中没有同名的静态成员变量,那么父子类共用一个父类中的静态成员;如果父子类中出现同名的静态成员变量,那么各用各的互不影响。