【发布时间】:2012-03-16 06:11:23
【问题描述】:
我在一些计算机科学测试中看到了下一段,我希望我能在这里很好地解释它的含义,因为我用谷歌搜索了一个小时,但找不到任何东西..
“当我们说 Java 语言有虚拟方法调用时,我们的意思是在 Java 应用程序中,执行的方法是由运行时的对象类型决定的”
这是什么意思?谁能更好地解释一下?
【问题讨论】:
我在一些计算机科学测试中看到了下一段,我希望我能在这里很好地解释它的含义,因为我用谷歌搜索了一个小时,但找不到任何东西..
“当我们说 Java 语言有虚拟方法调用时,我们的意思是在 Java 应用程序中,执行的方法是由运行时的对象类型决定的”
这是什么意思?谁能更好地解释一下?
【问题讨论】:
这些行的作者使用了virtual 的c++ 术语。
更好的术语是dynamic binding / dynamic dispatch。
这意味着,对象的动态type 正在“选择”将调用哪个方法,而不是静态类型。
例如:[伪代码]:
class A {
public void foo() { }
}
class B extends A {
public void foo() { }
}
调用时:
A obj = new B();
obj.foo();
将调用B.foo(),而不是A.foo(),因为obj 的动态类型是B。
【讨论】:
public void foo(int i) {} 那么A.foo() 会被选中吗?
我们的意思是在java应用程序中执行的方法是由运行时的对象类型决定的
interface Animal{
public void eat();
}
class Person implements Animal{
public void eat(){ System.out.println("Eating Food");}
}
class Eagle implements Animal{
public void eat(){ System.out.println("Eating Snake");}
}
主要
Animal animal = new Person();
animal.eat(); //it will print eating food
animal = new Eagle();
animal.eat(); //it will print eating snake
【讨论】:
假设你有一个 Fruit 类,它有两个子类 Orange 和 Banana。并假设 Fruit 有一个 String getColor() 方法。
Orange 可以覆盖getColor() 方法以返回“橙色”。 Banana 也一样,它可以返回“黄色”。
当某个方法使用 Fruit 类型的对象,并调用 getColor() 方法时,如果 Fruit 的类型实际上是 Banana,将调用的方法是 Banana.getColor()。
private void printColor(Fruit f) {
System.out.println(f.getColor());
}
...
Fruit fruit1 = new Banana();
Fruit fruit2 = new Orange();
printColor(fruit1); // prints yellow
printColor(fruit2); // prints orange
【讨论】:
Employee.java
public class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
}
VirtualMethod.java
class Salary extends Employee
{
private double salary; //Annual salary
public Salary(String name, String address, int number, double
salary)
{
super(name, address, number);
this.salary=salary;
}
public void mailCheck()
{
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to "
+ " with salary " + salary);
}
}
public class VirtualMethod
{
public static void main(String [] args)
{
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
输出
Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to with salary 3600.0
Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to with salary 2400.0
说明
在这里,我们实例化了两个Salary 对象。一个使用Salary 引用s,另一个使用Employee 引用e。
在调用s.mailCheck() 时,编译器会在编译时看到Salary 类中的mailCheck(),而JVM 在运行时调用Salary 类中的mailCheck()。
在e 上调用mailCheck() 完全不同,因为e 是Employee 引用。当编译器看到e.mailCheck() 时,编译器会看到Employee 类中的mailCheck() 方法。
这里,在编译时,编译器使用mailCheck() in Employee 来验证这个语句。但是,在运行时,JVM 会调用 Salary 类中的 mailCheck()。
【讨论】: