标签:invoke 因此 ati 编译器 方法调用 有关 import test 先来
我们先来看一下下面的例子:
package demo.jvm.test8? public class Demo2 { /**
*/ static abstract class Human { }
static class Man extends Human { }
static class Woman 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(Woman guy) { System.out.println("hello,lady!")? } public static void main(String[] args) { Human man = new Man()? Human woman = new Woman()? Demo2 sr = new Demo2()? sr.sayHello(man)? sr.sayHello(woman)?
} |
} 结果: hello,guy! hello,guy! package demo.jvm.test8? import demo.jvm.test8.Demo6.Man? import demo.jvm.test8.Demo6.Woman? public class Demo2 { /**
*/ static abstract class Human { }
static class Man extends Human { }
static class Woman 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(Woman guy) { System.out.println("hello,lady!")? } public static void main(String[] args) { Human man = new Man()? |
Human woman = new Woman()? Demo2 sr = new Demo2()?
sr.sayHello((Man)man)? sr.sayHello((Woman)woman)? } } 结果: hello,gentleman! hello,lady! 注意在这里之和传入的变量有关系的。 |
重载为什么为什么都是父类的呢?
我们来看一下下面的解释:
我们把上面代码中的"Human"称为变量的静态类型(Static Type),或者叫做的外观类型(Apparent Type),后面的"Man"则称为变量的实际类型(Actual Type),静态类型和
实际类型在程序中都可以发生一些变化,区别是静态类型的变化仅仅在使用时发生,变量本身的静态类型不会被改变,并且最终的静态类型是在编译期可知的;而实际类型变化的结果在运行期才可确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么。重载是编译器就决定了的。
解释了这两个概念,再回到代码清单8-6的样例代码中。main()里面的两次sayHello()方法调用,在方法接收者已经确定是对象"sr"的前提下,使用哪个重载版本,就完全取决于传入参数的数量和数据类型。代码中刻意地定义了两个静态类型相同但实际类型不同的变量,但虚拟机(准确地说是编译器)在重载时是通过参数的静态类型而不是实际类型作为判定依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数的静态类型决定使用哪个重载版本,所以选择了sayHello(Human)作为调用目标,并把这个方法的符号引用写到main()方法里的两条invokevirtual指令的参数中。
所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。静态分派的典型应用是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。另外,编译器虽然能确定出方法的重载版本,但在很多情况下这个重载版本并不是"唯一的",往往只能确定一个"更加合适的"版本。这种模糊的结论在由0和1构成的计算机世界中算是比较"稀罕"的事情,产生这种模糊结论的主要原因是字面量不需要定义,所以字面量没有显式的静态类型,它的静态类型只能通过语言上的规则去理解和推断。代码清单8-
7演示了何为"更加合适的"版本。
标签:invoke 因此 ati 编译器 方法调用 有关 import test 先来
原文地址:https://www.cnblogs.com/qingruihappy/p/9658000.html