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


person David Bower    schedule 26.11.2013    source источник


Ответы (2)


Вы можете использовать отражение Java, например, используя ConstructorUtils.invokeConstructor(...)

person Alex    schedule 26.11.2013
comment
Должен ли я использовать invokestatic для прямого вызова ConstructorUtils.invokeConstructor() или мне все же следует использовать invokedynamic и указать ConstructorUtils.invokeConstructor() в качестве цели сайта вызова? Какой из них предпочтительнее? - person David Bower; 26.11.2013
comment
Для статических методов можно использовать методы из MethodUtils... Для создания BigDecimal объекта BigDecimal.valueOf(...) предпочтительнее способ docs.oracle.com/javase/6/docs/api/java/math/. - person Alex; 26.11.2013
comment
На самом деле я говорю о генерации байт-кода. Если не удастся найти способ воспользоваться преимуществами Java 7 invokedynamic API, я буду использовать API отражения. - person David Bower; 26.11.2013

Вы хотите создать встроенный кеш. Первоначально ваш метод начальной загрузки будет возвращать сайт вызова, связанный с дескриптором метода, который проверяет свой тип аргумента, находит правильный конструктор для BigInteger (или любого другого типа — передайте этот тип в качестве статического аргумента методу начальной загрузки) и повторно связывает сайт вызова, чтобы сначала проверить этот тип и вызвать правильный конструктор, или вернуться к повторному поиску конструктора. Таким образом, если этот сайт вызова передает только строки, вы выполняете рефлексивный поиск конструктора только один раз, а дальнейшие вызовы — это просто проверка типа и прямой вызов конструктора. (Это очень похоже на то, что JVM делает для встроенных вызовов виртуальных методов.)

Я недостаточно хорошо знаком с invokedynamic, чтобы дать вам пример кода для этого, но я могу указать вам на JSR 252 Cookbook делает что-то подобное, что задокументировано с помощью выступление на JVM Language Summit 2011 и сопроводительные слайды.

person Jeffrey Bosboom    schedule 29.06.2014