Вызывать динамические и неявные методы
Как я понял из прочтения этого поста о новой инструкции invokedynamic bytecode в JDK 7, он позволяет вызывать методы для объектов, которые не определены статически в классе объекта, и разрешать вызовы этих методов некоторым конкретным статическим методам в некоторых другой класс, перехватывая разрешение цели вызова метода (пост приводит пример).
Означает ли это, что классы Java 7 могут иметь неявные методы, подобные Scala? Если нет, то как неявное разрешение метода в Scala отличается от разрешения метода invokedynamic?
2 ответа
Это совершенно не связано. Последствия в scala полностью решаются во время компиляции. Компилятор вставляет то, что вы могли бы написать сами. Если он не может этого сделать, во время компиляции возникает ошибка. InvokeDynamic - это поиск метода во время выполнения и сбой во время выполнения, если его не удается найти.
В частности, если вы пишете в Scala x.m()
где нет метода m в типе x, он будет искать неявное преобразование, то есть функцию, скажем, f, которая находится в области видимости (вы могли бы вызвать f в этой точке), которая помечена как неявная, которая будет принимать x в качестве параметра, и чей тип результата имеет метод m
(в правилах намного больше деталей, но это суть). Если он найдет такой метод, он заменит x.m()
по правильному типу f(x).m()
, С таким же успехом это можно было бы написать так в коде, как и в Java. Если такая функция f не может быть найдена, то возникает ошибка времени компиляции.
Это происходит точно так же, если вы звоните g(x)
а также x
не подходит для передачи g
, Если есть функция f
такой, что f(x)
имеет правильный тип, то он заменит код на g(f(x))
, Опять же, вы могли бы написать это сами в простой скале, и опять же, если такого метода нет, он не скомпилируется.
Dynamic не беспокоится о том, что во время компиляции m
метод в x
и ищет один во время выполнения. Вот как обычно работает динамический язык, такой как JRuby или Groovy. В scala есть что-то связанное, черта Dynamic (отмечена как экспериментальная).
Вызванный динамический байт-код поможет ускорить динамические языки в JVM. Это также ускорит доступ к структурным типам в Scala. Альтернативой invokedynamic (и единственной опцией до JDK 7) является рефлексия, которая действительно медленная.
Java-язык статически типизирован и не имеет функций, использующих invokedynamic (кроме явных отражающих вызовов методов с использованием java.lang.invoke.MethodHandle, в соответствии с этим вопросом).
Scala последствия на самом деле статически разрешены, и, следовательно, не связаны с invokedynamic. Для получения подробной информации о том, как это работает, см. Превосходное разоблачение Дэниэла Собрала: где Scala ищет возможные последствия?