invokedynamic and implicit methods

2019-05-05 10:46发布

问题:

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?

回答1:

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 method m (there are a lot more details in the rules, but this is the essence). If it finds such a method, then it will replace x.m() by the properly typed f(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) and x is not of the right type to be passed to g. If there is a function f such that f(x) has the proper type, then it will replace the code by g(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 in x, 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).



回答2:

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?