什么是java中的虚方法调用?

时间:2012-02-26 14:01:23

标签: java methods runtime

我在一些计算机科学考试中看到了下一段,我希望我能在这里得到一个很好的解释,因为我用谷歌搜索了一个小时,找不到任何东西..

“当我们说Java语言虚方法调用时,我们的意思是在java应用程序中,执行的方法由运行时的对象类型决定”

这是什么意思?任何人都可以更好地解释它吗?

4 个答案:

答案 0 :(得分:33)

这些行的作者使用了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(),因为动态类型objB

答案 1 :(得分:13)

  

我们的意思是在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

答案 2 :(得分:4)

假设你有一个类Fruit,有两个子类Orange和Banana。假设Fruit有String getColor()方法。

Orange可以覆盖getColor()方法以返回“orange”。香蕉也是如此,它可以让它返回“黄色”。

当某些方法使用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     

答案 3 :(得分:1)

<强> 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()时,编译器在编译时在mailCheck()类中看到Salary,并且JVM在运行时调用mailCheck()类中的Salary

mailCheck()上调用e是完全不同的,因为eEmployee引用。当编译器看到e.mailCheck()时,编译器会在mailCheck()类中看到Employee方法。

这里,在编译时,编译器使用mailCheck()中的Employee来验证此语句。但是,在运行时,JVM会在mailCheck()类中调用Salary