深入理解Java重载与重写

  我们都知道Java有三大宝,分别是:多态、封装、继承。其中多态主要体现就是重写与重载(有些人认为重载根本不属于多态)两种方式,那么今天就结合研读过JVM之后自己的理解来聊聊重载与重写的VM内部是怎么实现的,是怎么找到最后执行的方法的。

  在分析重载与重写这两个之前,我们必须要知道一些概念:分派、静态分派、动态分派、实际类型、静态类型....(之后涉及到的会边介绍别举例才能更好地理解)

一、相关的概念 1、静态类型与实际类型

  先看以下一个重载例子的输出,再进一步介绍:

public class StaticDispatch {
   
    static abstract class Human{  }
    static class Man extends Human{  }
    static class Women extends Human{    }
    //三个方法重载
    public void sayHello(Human guy) {
        System.out.println("hello guy!");
    }
    public void sayHello(Man guy) {
        System.out.println("hello gentleman!");
    }
    public void sayHello(Women guy) {
        System.out.println("hello laday!");
    }
    public static void main(String[] args) {
        Human man = new Man();//upcast
        Human woman = new Women();//upcast
        StaticDispatch sd = new StaticDispatch();
        //输出结果为:hello guy!
        sd.sayHello(man);
        sd.sayHello(woman);
    }
}

大多数都应该能知道最后的输出结果为:

hello, guy
hello, guy

这是为什么呢?根据输出来看man与woman就是Human类,这肯定是成立的,通过向上转型成基类(父类)可以使用getClass()或者instanceof确定,我们先不研究为什么吧。再通过重写的一个例子:

public class DynamicDispatch {
    static abstract class Human{ 
        protected void sayHello("hello, guy");
    }
    static class Man extends Human{

@Override
        protected void sayHello() {
            System.out.println("man say hello");
        } 
    }
    static class Women extends Human{

@Override
        protected void sayHello() {
            System.out.println("women say hello");
        }   
    }
    public static void main(String[] args) {
        Human man = new Man();
        Human women = new Women();
        man.sayHello();
        women.sayHello();
        man = new Women();
        man.sayHello();
    }

输出结果:

man say hello
women say hello
women say hello

  Man与Women重写了基类Human的sayHello()方法,输出的就是:man say hello women say hello而不是hello, guy,之后得特别注意man = new Women()并不是将man对象转为Women对象,其实就是将再复制了一个指向Woment的对象引用赋值给man,或者说man的指向由之前的Man变为Women(可能描述不太准准确),所以其实man = new Women()的man就是实际类型Women的一个对象实例,本质就是为实际类型。输出women say hello便能理解!

  那么如果不重写父类的方法呢?

public class DynamicDispatch {
    static abstract class Human{ 
        protected void sayHello() {
            System.out.println("hello, guy");
        };
    }
    static class Man extends Human{

/*@Override
        protected void sayHello() {
            //System.out.println("man say hello");
        } */
    }
    static class Women extends Human{

/*@Override
        protected void sayHello() {
            //System.out.println("women say hello");
        }*/   
    }
    public static void main(String[] args) {
        Human man = new Man();
        Human women = new Women();
        man.sayHello();
        women.sayHello();
        man = new Women();
        man.sayHello();
    }
}

结果为:

hello, guy
hello, guy
hello, guy

这什么我们又会问这是为什么呢?先不急,我们先了解静态类型、实际类型等几个概念之后再进一步介绍。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d626fb0522d37bc12b9fa28ca61a9e7c.html