Краткий ответ: Вы не можете получить доступ к Groovy "мета-методам" из Java.
Длинный ответ:
DefaultGroovyMethods.getMetaClass(..)
- это , а не метод, который может быть статически скомпилирован в байт-код Java.
[Исправление:
Тем временем Дон опубликовал ответ, предлагая привести к GroovyObject
. Это правильно, и таким образом вы сможете вызывать мета-методы Groovy следующим образом:
List<Book> books = (List<Book>)
((GroovyObject) Book).invokeMethod(
"findAllByAuthorAndTitle", new String[] {"author", "title"})
(или аналогичный). - Тем не менее, это нецелесообразно для повседневного программирования. ]
Посмотрите на DefaultGroovyMethods
ApiDocs . Первым параметром каждого метода является тип времени выполнения объекта. Оставшаяся часть соответствующего метода формирует подпись метода для использования в коде Groovy. Вы уже будете знакомы со многими из них.
Все эти «мета-методы времени выполнения» не статически скомпилированы в GroovyObject
((почти) любой объект Groovy, производный от этого типа), но при вызове динамически отправляются во время выполнения - обычно с использованием метода GroovyObject.invokeMethod(String, Object)
.
Итак, ваш Java-код вызывает метод, который просто не существует во время компиляции. - Но как Groovy-код может ссылаться на этот метод, если он не скомпилирован в байт-код Java? - Байт-код Groovy (Java) не ссылается напрямую на методы (конструкторы, свойства и т. Д.), А создает структуры, которые вызываются во время выполнения для динамической отправки.
Ваш тестовый класс, например, написанный на Groovy, скомпилирует это (сокращенно для ясности):
public class JavaGroovyTest extends TestCase
implements GroovyObject
{
public JavaGroovyTest()
{
JavaGroovyTest this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
MetaClass tmp12_9 = $getStaticMetaClass(); this.metaClass = ((MetaClass)ScriptBytecodeAdapter.castToType(tmp12_9, $get$$class$groovy$lang$MetaClass())); tmp12_9;
}
public void testGroovyClasses() { CallSite[] arrayOfCallSite = $getCallSiteArray(); Model m = arrayOfCallSite[0].callConstructor($get$$class$Model());
arrayOfCallSite[1].callStatic($get$$class$JavaGroovyTest(), m);
arrayOfCallSite[2].callStatic($get$$class$JavaGroovyTest(), $const$0, arrayOfCallSite[3].call(arrayOfCallSite[4].call(arrayOfCallSite[5].call(m)))); return;
}
}
Когда этот код выполняется, среда исполнения Groovy выполнит сотни, тысячи, а иногда и миллиарды поисков ;-), чтобы, наконец, вызывать метод не напрямую, а посредством вызова invokeMethod(..)
, подобного отражению.
Большинство частей языка программирования Groovy (включая сборщики и другие библиотеки) в значительной степени полагаются на эту концепцию метапрограммирования , которая может быть реализована в во время компиляции или выполнения .
К сожалению, Groovy предпочитает последнее, хотя все динамически добавленные функции не скомпилированы в байт-код Java и могут not напрямую вызываться кодом Java.