【问题标题】:Subtyping polymorphism: Always late binding?子类型多态性:总是后期绑定?
【发布时间】:2016-01-08 20:55:24
【问题描述】:

This 维基百科声明:

由于以前不知道多态对象的具体类型 运行时(通常),执行的函数是动态绑定的。 以下面的 Java 代码为例:

 public void foo(java.util.List<String> list) {
     list.add("bar");  
 }

List 是一个接口,所以 list 必须引用它的子类型。是不是一个 对 LinkedList、ArrayList 或其他一些子类型的引用 列表? add 引用的实际方法直到运行时才知道。

考虑这个例子:

List<String> list;

list = new LinkedList<String>();
foo(list);

list = new ArrayList<String>();
foo(list);

为什么这里引用的实际方法直到运行时才知道?编译器不能只检查每个对象 list 分配给哪个类型的 foo 调用吗?当然,这只有在程序具有确定性且不涉及随机性(例如用户交互)时才有可能。

这是(一般)引用的陈述中的是关于还是我的理解错误?

在程序是确定性的特殊情况下,是使用静态绑定还是 - 在 Java 中 - 总是使用动态绑定,不管有什么可能?如果有,为什么?

【问题讨论】:

  • 可以,但那将是很多工作而收效甚微。
  • @OliverCharlesworth,收获很大,超过了很多工作,因此它确实做到了!

标签: java polymorphism late-binding static-binding


【解决方案1】:

该声明谈到了一般案例。仅给出 Wikipedia 示例的代码,无法判断 list 参数的具体类型。在您的示例中,可以告诉具体类型。

Java 运行时是允许的,如果它能够检测到变量的具体类型,它实际上会去虚拟化方法调用。

如果您对该主题感兴趣:这是一篇讨论去虚拟化技术的link 论文。

【讨论】:

    【解决方案2】:

    在将 java 源代码编译为 java 字节码的过程中,没有进行去虚拟化。否则这将是相当脆弱的。请注意,编译后的 java 类通常保持二进制兼容性(有一些已知的例外)。因此,如果您的 foo 位于单独的类中并且您只重新编译这个类,那么调用 foo 的类应该可以使用新代码而无需重新编译。

    然而,去虚拟化在运行时是可能的,并且实际上由大多数现代 JVM(包括 Oracle HotSpot JVM,或当然)执行。该方法很可能在 JIT 编译期间完全内联:foo 调用、LinkedList.addArrayList.add 方法都将合并到调用者方法的主体中。

    所以总的来说维基百科的引用是正确的:add 引用的实际方法直到运行时才知道。但这并不意味着调用仍然是多态的,因为 JVM 运行时是相当复杂的事情,包括解释器、JIT 编译和 JIT 编译代码的执行。

    【讨论】:

      猜你喜欢
      • 2020-07-30
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多