我们都知道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
这什么我们又会问这是为什么呢?先不急,我们先了解静态类型、实际类型等几个概念之后再进一步介绍。