问题描述
我想生成一个类的字节码,该类将方法引用作为参数传递给另一个方法。 例如:
public class GeneratedClass {
public GeneratedClass() {
Test.foo((Function)Test::getId)
}
}
使用 ByteBuddy 我可以生成一个带有自定义构造函数的类,并创建一个 InvokeDynamic
来表示 Test::getId
,但问题是我无法将 InvokeDynamic
作为参数传递给我的MethodCall
。我目前的实现如下:
var fooMethod = Test.class.getmethod("foo",Function.class);
InvokeDynamic methodRef = InvokeDynamic.lambda(Test.class.getmethod("getId"),Function.class)
.withoutArguments();
new ByteBuddy()
.subclass(Object.class,ConstructorStrategy.Default.NO_CONSTRUCTORS)
.name("GeneratedClass")
.defineConstructor(Visibility.PUBLIC)
.intercept(
MethodCall.invoke(fooMethod)
.with((Object)null) \\I want to pass the methodRef instead of null
.andThen(methodRef)
).make()
.saveIn(new File("target"));
public class GeneratedClass {
public GeneratedClass() {
Test.foo((Function)null);
Test::getId;
}
}
解决方法
截至今天,DSL 不支持此功能,但您可以提供自定义 StackManipulation
作为 with
的参数。在您的情况下,您需要为此解决 MethodInvocation
。
通过一个小技巧,你可以在今天实现它,但创建一个辅助方法:
builder = builder
.defineMethod("mylambda",Function.class,Visibility.PRIVATE,Ownership.STATIC)
.intercept(methodRef)
然后您可以使用 MethodCall
调用此方法并将其作为参数传递。