调用动态和隐式方法
据我了解,阅读这篇关于新invokedynamic的文章JDK 7 中的字节码指令,它使得可以调用对象类中未静态定义的对象的方法,并通过拦截方法调用目标解析(帖子给出一个例子)。
这是否意味着 Java 7 类可以像 Scala 一样拥有隐式方法?如果不是,Scala 中的隐式方法解析与调用动态方法解析有何不同?
As I understand from reading this post about the new invokedynamic bytecode instruction in JDK 7, it makes it possible to call methods on the objects which are not statically defined in the object's class and have those method calls be resolved to some concrete static methods in some other class by intercepting the method call target resolution (the post gives an example).
Does this mean that Java 7 classes can have implicit methods like Scala has? If not how is implicit method resolution in Scala different from the invokedynamic method resolution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是完全不相关的。 scala 中的隐式在编译时完全解析。编译器会插入一些您也可以自己编写的内容。如果不能做到这一点,在编译时就会出现错误。 InvokeDynamic 是在运行时查找方法,如果找不到则在运行时失败。
具体来说,如果您在 scala
xm()
中编写,其中类型 x 中没有方法 m,它将查找隐式转换,即一个函数,例如 f,它在范围内(您可以此时调用 f),它被标记为隐式,它将接受 x 作为参数,其结果类型有一个方法m
(还有更多详细信息在规则中,但这就是本质)。如果它找到这样的方法,那么它将用正确键入的f(x).m()
替换xm()
。它也可以在代码中这样编写,而且在 java 中也必须这样做。如果找不到这样的函数 f,则存在编译时错误。如果您调用
g(x)
并且x
不是传递给g
的正确类型,也会发生同样的情况。如果存在一个函数f
使得f(x)
具有正确的类型,那么它将用g(f(x))
替换代码代码>.同样,你可以自己用普通的 scala 编写它,同样,如果没有这样的方法,它将无法编译。动态就是在编译时不用过多担心
x
中是否有m
方法,而在运行时寻找。这就是像 JRuby 或 Groovy 这样的动态语言通常的工作方式。 scala 中有一些相关的东西,trait Dynamic(标记为实验性的)。It is completely unrelated. Implicits in scala are fully resolved at compile time. The compiler inserts something that you could as well have written yourself. If it cannot do that, at compile time, there is an error. InvokeDynamic is about finding the method at runtime and failing at runtime if it cannot be found.
Specifically, if you write in scala
x.m()
where there is no method m in type x, it will look for an implicit conversion, that is a function, say f, which is in scope (you could call f at this point), which is marked as implicit, which will accept x as a parameter, and whose result type has a methodm
(there are a lot more details in the rules, but this is the essence). If it finds such a method, then it will replacex.m()
by the properly typedf(x).m()
. It could just as well have been written that way in the code, and it would have to in java. If no such function f can be found, then there is a compile time error.It happens just the same way if you call
g(x)
andx
is not of the right type to be passed tog
. If there is a functionf
such thatf(x)
has the proper type, then it will replace the code byg(f(x))
. Again, you could have written that yourself in plain scala, and again, if there is no such method, it will not compile.Dynamic is about not worrying too much at compile time whether there is an
m
method inx
, and looking for one at runtime. This is how a dynamic language like JRuby or Groovy typically works. There is something related in scala, trait Dynamic (marked experimental).invokedynamic 字节码将有助于加速 JVM 上的动态语言。它还将加快对 Scala 中结构类型的访问。 invokedynamic 的替代方案(也是 JDK 7 之前的唯一选项)是反射,它非常慢。
Java 语言是静态类型的,并且不具有使用 invokedynamic 的功能(除了使用 java.lang.invoke.MethodHandle,根据 这个问题)。
Scala 隐式实际上是静态解析的,因此与 invokedynamic 无关。有关其工作原理的详细信息,请参阅 Daniel Sobral 的精彩揭露:Scala 在哪里寻找隐式?
The invokedynamic bytecode will help speed up dynamic languages on the JVM. It will also speed up accesses to structural types in Scala. The alternative to invokedynamic (and only option prior to JDK 7) is reflection, which is really slow.
Java-the-language is statically typed, and doesn't have features that use invokedynamic (apart from explicit reflective method calls using java.lang.invoke.MethodHandle, according to this question).
Scala implicits are actually statically resolved, and thus unrelated to invokedynamic. For details about how it works, see Daniel Sobral's excellent expose: Where does Scala look for implicits?