深入深刻深到不能再深的理解java中的重载和重写

面向对象的三个特性

面向对象有三个重要的特性:多态,继承,封装。

多态的表现

多态的在java中的应用体现在方法的重载和重写。
重载:字面上的意义一个类里面,有同名但是参数必须不相同的方法。(这里的”不同参数“必须不是泛型,比如List<String> 和List<Integer>)
重写:对应的是子类去重写了父类的方法,有自己的实现,不能更改方法的参数和名称。
但是在JVM中是怎么实现的呢?JVM对于这两种方式是怎么区分的?

方法的重载

我们都知道,.java的源文件都会被编译成.class的文件,class文件是一堆二进制流。
执行 方法的指令在JVM里面有四个
invokestatic 执行静态的方法
invokespecial 执行构造方法,或者调用父类的方法(对应super关键字)
invokedynamic 执行动态语言的方法
invokevirtual 执行普通方法

考虑下面代码

class A{
     pulic void print(B b){
       }
    pulic void print(C c){
       }
}
 public static void main(String args[]){

        A a = new A();
        B b = new C();
        a.print(b);
    }

当我们调用 a.print(b)的时候,虚拟机会根据你传递参数的静态类型去匹配方法,这是一个静态分派的过程。
什么叫静态类型 比如 B b = new C();C是派生B的,我们经常在java中这么写,没有任何问题。这里对象B的静态类型就是B,但是它的实际类型是C。
我们调用a.print(b)的时候它匹配的是 print(B b)这个方法,所以编译器它不会考虑这个b的实际类型(因为B的实际类型会被执行invospecial去指定)是什么,它直接在编译成字节码阶段就把这个方法匹配了。
它的字节码


image.png

但是还有一个点要注意,静态类型是可以强转的

 public static void main(String args[]){

        A a = new A();
        B b = new C();
        a.print((C)b);
    }

这时候它匹配的就是print(C c)这个方法了


image.png

方法重载:只会根据参数的静态类型去匹配。

方法的重写

方法的重写:表现的就是重写父类的方法

public class B {

    public void callMe(){
        System.out.print("B is call");
    }
}
public class C extends B {
    @Override
    public void callMe() {
        System.out.print("C is call");
    }
}

   public static void main(String args[]){
        B b = new B();
        b.callMe();
        B c = new C();
        c.callMe();
    }

在编译阶段它只会在静态类型中去匹配方法,所以尽管b和c 的实际类型不同,但它们执行callMe的字节码指令是相同的


image.png

但是虚拟机在执行这个指令的时候,它会先在操作数栈中拿到调用这个方法的对象,然后根据这个对象的实际类型去匹配方法,如果这个类型里面没有,则它就会去父类去找一直递归直到找到为止。否则将会抛出MethodNotFoundException。
这样递归非常麻烦,所以虚拟机会对每一个clas对象都生成一个方法表。(这个在连接阶段会准备好,一般再类变量初始为零值之后)
它里面保存了这个类所有方法直接引用(也是就能再虚拟机中找到执行的代码),保存的顺序先是父类的方法,然后才是自己的方法,如果子类重写了父类的方法,它会将这个指针指向自己的实现,否则指向父类,这样的好处是只用查找一次,不管类型怎么切换,只要他们的方法表的顺序是一致的,我就可以根据这个下标去找到对应的方法入口。


image.png

比如使用son的对象 son.hardChoice(),会再son的方法表里面找到方法入口,虚拟机会记住这个下标,当我再使用
father.hardChoice()的时候,直接切换到Father的方法表,通过记住的这个下标找到方法入口,不用去遍历了!
同理接口也有对应的接口表,它里面的方法就是无序的了,无法通过下标去查找,每一次调用方法都只能去遍历整个表,所以一般来说查找接口方法比查找普通方法要慢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容