问题
After reading the documentation and a few Github issues, which proved to be particularly useful, I came to understand that in ByteBuddy terminology a static
field must be set to its initial value by a LoadedTypeInitializer
of some kind.
I didn't know what to do with a LoadedTypeInitializer.ForStaticField
once I had created it. Then, thankfully, I just happened to stumble across the initializer()
method of DynamicType.Builder
. Here is my recipe (which does not work):
builder = builder
.initializer(new LoadedTypeInitializer.ForStaticField("$frob", this.frob))
.defineField("$frob",
Frob.class,
Ownership.STATIC,
SyntheticState.SYNTHETIC,
Visibility.PRIVATE,
FieldManifestation.FINAL);
If I examine the value of this field via reflection after loading the type, the field is there but it is set to null
.
If I remove FieldManifestation.FINAL
from this recipe, it works. But ideally I'd like my field to be final
. Is this possible?
回答1:
The default initializer requires a non-final field but you can implement it yourself to set the value for a final field by calling setAccessible
to true
.
A more elegant solution might be to set the field in a static initializer. The problem with this approach that you can only set values that you assemble from compile-time constants (primitives and strings) unless you can access the field from somewhere when the initializer is invoked. As for example:
builder = builder.invokeable(isTypeInitializer()).intercept(MethodCall.invoke(...).setsField(...))
You would need to create a FieldDescription.Latent
to reference the field you have created.
来源:https://stackoverflow.com/questions/61219512/how-do-i-define-a-private-static-final-field-using-bytebuddy-with-an-initial-com