隐藏和覆盖的区别和用法

讲隐藏和覆盖之前先看两个概念:静态类型动态类型

任何一个引用变量都有两个类型:一个叫静态类型,也就是定义该引用变量的类型;另一个叫动态类型,也就是该引用实际指向的对象类型。

比如对于两个类A和类B,有:A a=new B();

那么,引用a的静态类型就是A,动态类型就是B。

java中引用的静态类型在编译的时候就可以确认,但是编译器无法得知这个引用的动态类型;只有当程序运行时,通过RTTI就可以检查出引用的动态类型。

再介绍一下,java中绑定的概念:对于一个程序,可以有很多的方法。这些方法的名称、参数类型和参数数量都可能相同或者不同,那么在调用一个方法的时候,如何将一个方法和该方法所在的类关联起来,这就是绑定。java中的绑定分为静态绑定和动态绑定。

静态绑定:所有依赖于静态类型来将某方法和该方法所在的类关联起来的动作都是静态绑定。因为静态绑定在程序运行前发生,所有又叫前期绑定。

动态绑定:所有依赖于动态类型来将某方法和该方法所在的类关联起来的动作都是动态绑定。因为动态绑定是在程序运行时,通过RTTI实现,所以又叫后期绑定。

举例:假如有一个父类Father和一个子类Son,子类重写了父类中的某个方法method()。有以下语句:

Father father=new Son();

father.method();

对于这个例子,静态绑定的过程是:java文件编译时,编译器检查出引用father的静态类型是Father类,由于将method()方法和父类Father关联起来。也就是说,程序运行前编译器是无法检查出引用father的动态类型的,所以会直接调用静态类型中对应的方法。

而动态绑定的过程是:当这个java程序运行起来了,RTTI检查出引用father的动态类型是Son类时,会将method()方法和子类Son关联起来,也就是决定调用动态类型Son类中的method()方法。具体过程为:①JVM提取对象的实际类型的方法表;②JVM搜索方法签名;③调用方法。

另外,要补充的是:java中类的属性也都是静态绑定的。这是因为静态绑定是有很多的好处,它可以让我们在编译期就发现程序中的错误,而不是在运行期。这样就可以提高程序的运行效率!而对方法采取动态绑定是为了实现多态。

----------------------------------------------------------------------------------------------------------------分割线------------------------------------------------------------------------------------------------------------------

下面来说一下,java中的隐藏和覆盖的概念。我们知道,当子类继承父类时,除了继承父类所有的成员变量和成员方法之外,还可以声明自己的成员变量和成员方法。那么,如果父类和子类的成员变量和方法同名会发生什么?假设有一个父类Father和一个子类Son。父类有一个成员变量a=0;有一个静态成员变量b=0;有一个成员方法a,输出0;有一个静态成员方法b,输出0。子类分别重写这些变量和方法,只是修改变量的值和方法的输出,全部改为1.   我们再声明一个静态类型是父类,动态类型是子类的引用:

Father father=new Son();

通过这个引用访问子类的变量和调用子类的方法,那么,会有以下结论:

1、所有的成员变量(不管是静态还是非静态)都只进行静态绑定,所以JVM的绑定结果会是:直接访问静态类型中的成员变量,也就是父类的成员变量,输出0.

2、对于静态方法,也是只进行静态绑定,所以JVM会通过引用的静态类型,也就是Father类,来进行绑定,结果为:直接调用父类中的静态方法,输出0.

3、对于非静态方法,会进行动态绑定,JVM检查出引用father的动态类型,也就是Son类,绑定结果为:调用子类中的静态方法,输出1.

对于1和2这两种情况,子类继承父类后,父类的属性和静态方法并没有被子类抹去,通过相应的引用可以访问的到。但是在子类中不能显示地看到,这种情况就称为隐藏。

而对于3这种情况,子类继承父类后,父类的非静态方法被子类重写后覆盖上去,通过相应的引用也访问不到了(除非创建父类的对象来调用)。这种情况称为覆盖。

总结一下,就是,子类继承父类后:

父类的成员变量只会被隐藏,而且支持交叉隐藏(比如静态变量被非静态变量隐藏)。父类的静态方法只会被静态方法隐藏,不支持交叉隐藏。父类的非静态方法会被覆盖,但是不能交叉覆盖。

代码测试如下:

package test;
/* 隐藏和覆盖的区别 */
public class HideAndCover {
    public static void main(String[] args) {
        Father father=new Son();
        System.out.println(father.a);
        System.out.println(father.b);
        father.c();
        father.d();
    }

}
//声明父类
class Father{
    static int a=0;
    int b=0;
    void c() {
        System.out.println(0);
    }
    static void d() {
        System.out.println(0);
    }
}
//声明子类
class Son extends Father{
    static int a=1;
    int b=1;
    void c() {
        System.out.println(1);
    }
    static void d() {
        System.out.println(1);
    }
}

运行结果为:

0

0

1

0

最后附上多态的三个必要条件:

①继承

②重写

③父类引用指向子类对象

——over。

时间: 2024-08-04 22:34:59

隐藏和覆盖的区别和用法的相关文章

重载、隐藏、覆盖的区别

成员函数的重载.隐藏.覆盖有时候难以辨别,如果你还不太理解,请往下看. 首先,我们先了解一下成员函数被重载,覆盖,隐藏的特征. 成员函数被重载的特征: (1)在同一个类中 (2)函数名相同,参数不同(参数的个数,参数的类型) (3)无返回值 成员函数被覆盖的特征: (1)不在同一个类中 (2)函数名相同,参数相同 (3)基类函数必须有vritual关键字 成员函数被隐藏的特征: (1)不在同一类中 (2)函数名相同,若参数不同,无论有无vritual关键字,基类函数都被隐藏. 若参数相同,基类函

【转】c++重载、覆盖、隐藏——理不清的区别

原文网址:http://blog.sina.com.cn/s/blog_492d601f0100jqqm.html 再次把林锐博士的<高质量c++编程指南>翻出来看的时候,再一次的觉得这是一本难得的好书.实践派写的东西跟理论派和翻译派写的书有着本质的 区别,每次读这本书都觉得为什么自己读了这么多遍,还是会犯一些上面讲的小错误,编代码有时候莫名其妙又会把自己转糊涂了.这本书浅显易懂,而且提到了编 程过程中应该注意的很多细节,里面展开来讲的细节又偏偏是我觉得最为薄弱的环节,如果大家想学或者正在学习

Java:类与继承(隐藏和覆盖的问题)

盒子先生金金 Java:类与继承(隐藏和覆盖的问题) Java:类与继承 Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知识.首先,我们讲述一下与类的初始化相关的东西,然后再从几个方面阐述继承这一大特性.以下是本文的目录大纲: 一.你了解类吗? 二.你了解继承吗? 三.常见的面试笔试题 若有不正之处,请多多谅解并欢迎批评指正. 请尊重作者劳动成果

C++父子类继承时的隐藏、覆盖、重载

存在父子类继承关系时,若有同名成员函数同时存在,会发生隐藏.覆盖和重载这几种情况.对于初学者也比较容易混淆,为此,我整理了一下我的个人看法,仅供参考.希望对大家理解有帮助,也欢迎指正. 1.父子类继承关系: 子类复制父类全部成员 首先,理解父子类的继承关系是怎样发生的.在此基础上就很容易理解它们之间的关系和区别. 每一个类有它自己的成员变量和成员函数,是一个独立的空间整体.当子类继承父类时,会将父类的全部成员全部复制一份,作为子类的成员,但是,同时也会标记这些成员是从父类中继承的,与子类本身的成

margin和padding的区别和用法

margin和padding的区别和用法 什么是margin.padding? marigin:就是外边距.padding:就是内边距.怎么就容易记住两者呢? 马蓉大家都知道吧,给王宝强带帽子的那位,假如你认识了马蓉是不是想离他远点呢?而马蓉的拼音是marong,是不是和margin特别像呢?那么你看着maring是不是就知道了margin是外边距呢? 那么padding就更容易记住了,panda是熊猫大家都是知道吧,熊猫是我们中国的国宝而且都很可爱,所以看见padding就知道了是内边距是吧.

Position属性四个值:static、fixed、absolute和relative的区别和用法

Position属性四个值:static.fixed.absolute和relative的区别和用法 在用CSS+DIV进行布局的时候,一直对position的四个属性值relative,absolute,static,fixed分的不是很清楚,以致经常会出现让人很郁闷的结果.今天研究了一下,总算有所了解.在此总结一下: 先看下各个属性值的定义: 1.static(静态定位):默认值.没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声

c++ 函数的隐藏和覆盖

转自:http://bbs.csdn.net/topics/390082114 在看<高质量c/c++>中看到了函数的隐藏和覆盖是这么说的: 覆盖的是指子类函数覆盖基类函数在不同的类内(分别位于子类和父类).同名同参.基类的函数名前必须有virtual关键字.隐藏指派生类的函数隐藏了基类的同名函数如果派生类函数与基类函数同名,但参数不同,无论基类函数前是否有virtual修饰,基类函数被隐.如果派生类函数与基类函数同名,参数也相同,但是基类函数前无virtual修饰,基类函数被隐藏. 1 cl

div与span区别及用法

DIV与SPAN区别及div与san用法篇 接下来了解在div+css开发的时候在html网页制作,特别是标签运用中div和span的区别及用法.新手在使用web标准(div css)开发网页的时候,遇到第一个问题是div与span有什么区别,什么时候用div,什么时候用span标签. 目录 特点与区别 小结 知识扩展 案例效果演示 一.DIV与SPAN的区别与特点   -   TOP 以下是在没有对开发网页页面设置css样式时候情况下,系统默认情况下的介绍div与span区别div占用的位置是

Struts2中的ActionContext和ServletActionContext的区别和用法

今天学习Struts2的时候遇到"访问和添加属性"的问题,然后就学到了ActionContext和ServletActionContext之间的区别和用法,然后又在网上搜了下别人的文章大致了解了一下,就想着总结一下. 参考文章1:http://www.cnblogs.com/tanglin_boy/archive/2010/01/18/1650871.html 参考文章2:http://blog.csdn.net/woshixuye/article/details/8172777 相信