Could not assign variables to fields via ByteBudy

问题描述 投票:0回答:0

我正在学习 ByteBuddy 并尝试使用以下代码。

我定义了一个带有重载方法的 Animal 接口,并尝试创建一个覆盖这两种方法的类。 效果很好。 然后我尝试在生成的类中有一个字段并尝试调用该字段。 那时我遇到了例外情况。

以下是我的代码:

public interface Animal {

    String sound();

    String sound(boolean loud);
}

以下是 Main::main 方法的代码片段。

DynamicType.Unloaded<Animal> dogClassUnloaded = new ByteBuddy()
        .subclass(Animal.class)
        .name("Dog")

        // we can use bytebuddy modifiers
        .defineField("colour", String.class, Visibility.PUBLIC, FieldManifestation.FINAL)

        .defineConstructor(Visibility.PUBLIC)
        // or java modifiers -> Modifier.FINAL + Modifier.PRIVATE like that
        .withParameter(String.class, "colour", Modifier.FINAL)
        .intercept(
                MethodCall.invokeSuper()
                        .andThen(
                                // field arguments are denoted by their index
                                FieldAccessor.ofField("colour").setsArgumentAt(0)
                        )
        )

        // There are different ways to match the methods, fields etc.
        // https://www.tabnine.com/code/java/classes/net.bytebuddy.matcher.ElementMatchers

        // intercepting no argument method
        .method(ElementMatchers.named("sound")
                .and(ElementMatchers.takesNoArguments())
        )
        .intercept(FixedValue.value("woof quiet"))


        // intercepting overloaded method with arguments
        .method(
                ElementMatchers.named("sound")
                        .and(ElementMatchers.takesArgument(0, boolean.class))
        )
        .intercept(FixedValue.value("woof woof loud"))

        .make();

Class<? extends Animal> dogClassLoaded = dogClassUnloaded
        .load(Main.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();

Animal dog = dogClassLoaded.getDeclaredConstructor(String.class).newInstance("black");
// Animal dog = dogClassLoaded.getDeclaredConstructor().newInstance();

var x = dog.sound();
var y = dog.sound(true);

System.out.println(x);
System.out.println(y);


// What if Dog.class has other methods / fields not in Animal.class
Field m = dogClassLoaded.getDeclaredField("colour");
String colour = (String) m.get(dog);
System.out.println(colour);

当我尝试执行时出现以下异常:

Exception in thread "main" java.lang.IllegalStateException: public Dog(java.lang.String) does not accept 0 arguments
    at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3553)
    at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3522)
    at net.bytebuddy.implementation.bytecode.ByteCodeAppender$Compound.apply(ByteCodeAppender.java:156)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:730)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:715)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:622)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:6043)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2224)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4050)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3734)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3986)
    at tutorial.example_1.Main.main(Main.java:55)

它指出 make() 方法没有正确编译。这意味着课程没有按预期构建。 我认为 MethodCall.invokeSuper() 是问题所在,因为超类是一个接口。

解决方案是什么? 我正在使用 Java-17 和最新版本的 bytebuddy (1.13)

byte-buddy java-17
© www.soinside.com 2019 - 2024. All rights reserved.