Как использовать invokedynamic для выполнения метода с полиморфизмом?
В динамическом языке для Java, где все переменные объявлены как java.lang.Object
Мне нужно вызвать встроенные классы Java. Например, java.math.BigDecimal
конструктор может принимать число, строку и т. д.
a = 10 // a is `java.lang.Object`
create java.math.BigDecimal(a) // should call constructor that accept number
a = '1.234' // a is `java.lang.Object`
create java.math.BigDecimal(a) // should call constructor that accept String
Здесь java.lang.invoke
что я могу использовать для генерации соответствующего MethodHandle
? MethodHandle
должен принять java.lang.Object
в качестве аргумента, но при вызове он должен вызвать правильный конструктор.
2 ответа
Вы можете использовать Java-отражение, например, используя ConstructorUtils.invokeConstructor(...)
Вы хотите создать встроенный кеш. Первоначально ваш метод начальной загрузки вернет сайт вызова, связанный с дескриптором метода, который проверяет его тип аргумента, находит соответствующий конструктор в BigInteger (или любом другом типе - передает этот тип в качестве статического аргумента методу начальной загрузки) и выполняет повторную ссылку сайт вызова, чтобы сначала проверить этот тип и вызвать правильный конструктор, или вернуться к поиску конструктора снова. Таким образом, если этот сайт вызова передает только строки, вы только один раз выполняете рефлексивный поиск для конструктора, а дальнейшие вызовы - это просто проверка типа и прямой вызов конструктора. (Это очень похоже на то, что делает JVM для встроенных вызовов виртуальных методов.)
Я не знаю invokedynamic достаточно хорошо, чтобы дать вам пример кода для этого, но я могу указать вам, что JSR 252 Cookbook делает нечто подобное, что описано в выступлении на JVM Language Summit 2011 и сопровождающих его слайдах.