How do I define a private static final field using ByteBuddy with an initial complex value?

此生再无相见时 提交于 2020-07-22 21:32:08

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!