【问题标题】:static binding and dynamic binding use case静态绑定和动态绑定用例
【发布时间】:2015-06-21 04:18:23
【问题描述】:

我们知道静态绑定发生在私有、静态、最终和重载方法上,而动态绑定发生在重写方法上。 但是,如果我的方法只是公共的,它既不是静态的,也不是被覆盖和重载的怎么办。

public class Test{
    public void print(){
        System.out.println("hello!");
    }
    public static void main(String args[]){
        Test t = new Test();
        t.print();
    }
}

谁能解释一下 print() 会发生什么绑定,因为它既没有重载也没有被覆盖。

【问题讨论】:

  • print 是什么?方法必须始终具有返回类型。
  • 请注意,重载的实例方法也是动态绑定的,就像任何其他实例方法一样。
  • 注意,重载的实例方法也是动态绑定的……你能举例说明一下吗?
  • @user2068260 假设一个 Bar 类有两个实例方法 foo(int) 和 foo(String)。 SubBar 类可以覆盖这两个方法 foo(int) 和 foo(String)。当您调用 someObject.foo(int) 或 someObject.foo(String) 时,将执行的方法取决于 someObject 的实际具体类型,就像任何其他实例方法一样。它重载的事实并没有改变任何东西。

标签: java


【解决方案1】:

Java 无论如何都会使用invokevirtual 来调用该方法(并且这是动态的),无论该方法是否已被覆盖。看字节码就更清楚了

public static void main(java.lang.String[]);
Code:
   0: new           #5                  // class Test
   3: dup
   4: invokespecial #6                  // Method "<init>":()V
   7: astore_1
   8: aload_1
   9: invokevirtual #7                  // Method print:()V
  12: return

第 9 行显示了调用虚拟。现在 JIT 编译器可能决定删除动态调度以实现更好的性能,It is one of the used techniques

【讨论】:

    【解决方案2】:

    您仍然在这里获得动态绑定,因为编译器不知道该方法没有覆盖。即时编译器可能会找出并优化调用,但就 Java 编译器而言,与方法 print() 的绑定是动态的。

    【讨论】:

    • 请注意,即使编译器知道它没有覆盖(因为该方法是最终方法),您仍然会有动态绑定,以防最终方法稍后变为非最终方法。
    【解决方案3】:

    您获得动态绑定。实际调用的test() 方法取决于对象的实际类型,而不是对象的声明类型。在您的示例中它没有被覆盖并不重要,该方法仍然是虚拟的并且可以被覆盖。

    注意main() 具有静态绑定,因为(作为静态方法)main() 方法取决于Test 类的实际类型。

    【讨论】:

      猜你喜欢
      • 2015-09-14
      • 2012-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      • 2016-04-02
      • 1970-01-01
      相关资源
      最近更新 更多