Как использовать 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 и сопровождающих его слайдах.

Другие вопросы по тегам