Как определить частное поле stati c final, используя ByteBuddy с начальным комплексным значением? - PullRequest
1 голос
/ 15 апреля 2020

После прочтения документации и нескольких проблем Github , которые оказались особенно полезными, я пришел к выводу, что в терминологии ByteBuddy поле static должно быть установлено в его начальное значение с помощью LoadedTypeInitializer некоторого вида.

Я не знал, что делать с LoadedTypeInitializer.ForStaticField, как только я его создал. Затем, к счастью, я просто наткнулся на initializer() метод DynamicType.Builder. Вот мой рецепт (который не работает):

builder = builder
  .initializer(new LoadedTypeInitializer.ForStaticField("$frob", this.frob))
  .defineField("$frob",
               Frob.class,
               Ownership.STATIC,
               SyntheticState.SYNTHETIC,
               Visibility.PRIVATE,
               FieldManifestation.FINAL);

Если я проверю значение этого поля с помощью отражения после загрузки типа, поле будет там, но оно установлено на null.

Если я удаляю FieldManifestation.FINAL из этого рецепта, он работает. Но в идеале я хотел бы, чтобы мое поле было final. Это возможно?

1 Ответ

0 голосов
/ 16 апреля 2020

Инициализатору по умолчанию требуется не конечное поле, но вы можете реализовать его самостоятельно, чтобы установить значение для конечного поля, вызвав setAccessible в true.

Более элегантным решением может быть установка поле в инициализаторе состояния c. Проблема этого подхода в том, что вы можете устанавливать значения, которые вы собираете только из констант времени компиляции (примитивов и строк), если только вы не можете получить доступ к полю откуда-то, когда вызывается инициализатор. Например:

builder = builder.invokeable(isTypeInitializer()).intercept(MethodCall.invoke(...).setsField(...))

Вам необходимо создать FieldDescription.Latent для ссылки на поле, которое вы создали.

...