正如我从阅读这篇关于 JDK 7 中新的 invokedynamic 字节码指令的帖子中了解到的那样,它可以调用对象类中未静态定义的对象上的方法,并将这些方法调用解析为某些具体的静态方法其他类通过拦截方法调用目标解析(帖子给出了例子)。
这是否意味着 Java 7 类可以拥有像 Scala 那样的隐式方法?如果不是,Scala 中的隐式方法解析与调用动态方法解析有何不同?
正如我从阅读这篇关于 JDK 7 中新的 invokedynamic 字节码指令的帖子中了解到的那样,它可以调用对象类中未静态定义的对象上的方法,并将这些方法调用解析为某些具体的静态方法其他类通过拦截方法调用目标解析(帖子给出了例子)。
这是否意味着 Java 7 类可以拥有像 Scala 那样的隐式方法?如果不是,Scala 中的隐式方法解析与调用动态方法解析有何不同?
这是完全无关的。scala 中的隐式在编译时完全解析。编译器会插入一些您也可以自己编写的内容。如果它不能做到这一点,在编译时,就会出现错误。InvokeDynamic 是关于在运行时查找方法,如果找不到则在运行时失败。
具体来说,如果你在 scalax.m()
中编写类型 x 中没有方法 m,它会寻找一个隐式转换,即一个函数,比如说 f,它在作用域内(你可以在此时调用 f),它被标记as implicit,它将接受 x 作为参数,并且其结果类型有一个方法m
(规则中有更多细节,但这就是本质)。如果它找到这样的方法,那么它将 x.m()
被正确键入的f(x).m()
. 它也可以在代码中以这种方式编写,并且必须在 java 中编写。如果找不到这样的函数 f,则存在编译时错误。
如果您调用g(x)
并且x
不是要传递给的正确类型,它会以同样的方式发生g
。如果有一个具有正确类型的函数f
,f(x)
那么它将用g(f(x))
. 再一次,你可以用普通的 scala 自己编写,同样,如果没有这样的方法,它将无法编译。
动态是在编译时不用过多担心 中是否有m
方法x
,并在运行时寻找方法。这就是像 JRuby 或 Groovy 这样的动态语言通常的工作方式。scala 中有一些相关的东西,trait Dynamic(标记为实验性的)。
invokedynamic 字节码将有助于加速 JVM 上的动态语言。它还将加快对 Scala 中结构类型的访问。invokedynamic 的替代方案(也是 JDK 7 之前的唯一选项)是反射,它真的很慢。
Java 语言是静态类型的,并且没有使用 invokedynamic 的功能(根据这个问题,除了使用java.lang.invoke.MethodHandle的显式反射方法调用)。
Scala 隐式实际上是静态解析的,因此与调用动态无关。有关其工作原理的详细信息,请参阅 Daniel Sobral 的出色揭露:Scala 在哪里寻找隐式?