【问题标题】:What is virtual method calling in java?java中的虚方法调用是什么?
【发布时间】:2012-03-16 06:11:23
【问题描述】:

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

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

这是什么意思?谁能更好地解释一下?

【问题讨论】:

标签: java methods runtime


【解决方案1】:

这些行的作者使用了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。

【讨论】:

  • 只是一个需要澄清的问题:如果 B 中的 foo 方法具有不同的签名,例如public void foo(int i) {} 那么A.foo() 会被选中吗?
  • @VanTheMan 是的,在这种情况下不会超载
  • 或者实际上,您的意思是在这种情况下该方法不是覆盖吗?据我了解,重载是指同名但参数不同的方法。而覆盖是指继承的方法具有相同的名称和相同的签名。
【解决方案2】:

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

【讨论】:

  • 谢谢!!我想我知道,但如果我错了,请纠正我:所以说“在java应用程序中,执行的方法由运行时的对象类型确定”,这意味着java仅在执行时确定对象?在您的示例中,animal.eat(第一个)将执行 Person 的方法,第二个它将执行 Eagle 的方法,这就是它的目的吗?
  • 没错,对象将被创建运行时,所以它是运行时决定
【解决方案3】:

假设你有一个 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     

【讨论】:

  • 谢谢 :) 我在前面的帖子中得到了答案,但这也是一个很好的解释。
【解决方案4】:

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()。

【讨论】:

  • 我知道这只是一个例子,但“class Salary extends Employee”不是建模。薪水不是雇员。
猜你喜欢
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 2013-02-01
相关资源
最近更新 更多