java中的重载就是说一个类里面有多个名字相同而参数列表不同的方法,重写是说同一个方法在子类里可以与父类有不同的行为,那jvm中是怎么实现的呢
先来解释重载,
-
public class Overload{
-
static class Human{
-
}
-
static class Man extends Human{
-
}
-
static class Woman extends Human{
-
}
-
void sayHello(Human man){
-
System.out.println("hello man");
-
}
-
void sayHello(Man man){
-
System.out.println("hello gentleman");
-
}
-
void sayHello(Woman man){
-
System.out.println("hello laddy");
-
}
-
public static void main(String[] args){
-
Human man=new Man();
-
Human woman=new Woman();
-
Overload over=new Overload();
-
over.sayHello(man);
-
over.sayHello(woman);
-
System.out.println("---------------------------");
-
over.sayHello((Man)man);
-
over.sayHello((Woman)woman);
-
}
-
}
over这个方法接收者对于参数类型为Man和Woman有不同的实现,请问上述代码在jvm执行时会是同样的结果吗?答案是不一样,因为=号左边的Human叫做静态类型,右边的new Man叫做实际类型,前者在编译期就以确定,后者得在运行期才可知,而重载是在编译期就确定了方法,因此第21,22行就选择了以作为以Human为参数的方法,同理:24,25分别选择以Man,Woman为参数的方法
再接下来是重写,
-
public class Overwrite{
-
static class Human{
-
void sayHello(){
-
}
-
}
-
static class Man extends Human{
-
void sayHello(){
-
System.out.println("hello gentleman");
-
}
-
}
-
static class Woman extends Human{
-
void sayHello(){
-
System.out.println("hello laddy");
-
}
-
}
-
public static void main(String[] args){
-
Human man=new Man();
-
Human woman=new Woman();
-
man.sayHello();
-
woman.sayHello();
-
}
-
}
19,20行首先得确定方法接收者,由于编译期不能确定方法接收者,得等到运行期,这也就是为什么重写得等到运行期才能确定的原因,用javap命令大概会看到这么几行输出
-
public static void main(java.lang.String[]);
-
Code:
-
0: new #2 // class Overwrite$Man
-
3: dup
-
4: invokespecial #3 // Method Overwrite$Man."":()V
-
7: astore_1
-
8: new #4 // class Overwrite$Woman
-
11: dup
-
12: invokespecial #5 // Method Overwrite$Woman."":()V
-
15: astore_2
-
16: aload_1
-
17: invokevirtual #6 // Method Overwrite$Human.sayHello:()V
-
20: aload_2
-
21: invokevirtual #6 // Method Overwrite$Human.sayHello:()V
-
24: return
-
}
aload_1,2就是加载new出来的那两个对象到栈顶,这样确定了方法接收者,再而按照从下到上(子类往父类走)的顺序确定方法,所以,方法签名完全一样(对应着静态类型也一样)但是由于方法接收者不一样,多态之重写就体现出来了
阅读(1914) | 评论(0) | 转发(0) |