Как создать класс с обновленным частным полем с помощью ByteBuddy?

Мне нужно создать класс с обновленным частным полем.

Это мой код:

public class ByteBuddyTest {

    public static class Foo {

    }

    public static class Bar {

        private Foo foo;

        public Foo getFoo() {
            return foo;
        }
    }

    public static void main(String[] args) throws Exception{
        Class<? extends Bar> clazz = new ByteBuddy()
            .subclass(Bar.class)
            .??? //LINE X
            .make()
            .load(ByteBuddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded();

        var bar1 = clazz
            .getDeclaredConstructor()
            .newInstance();
        System.out.println(bar1.getFoo());

    }
}

В line X мне нужно установить новый экземпляр Foo в поле Bar.foo для каждого экземпляра Bar. Обратите внимание, что мне нужно создать много экземпляров Bar, поэтому я хочу создать класс с ByteByddy только один раз. Может ли кто-нибудь сказать, как это сделать?

Если вам нужно создать много экземпляров Bar, то почему это статический класс? Такие хаки, как ByteBuddy, никогда не должны быть вашей первой мыслью. Почему нельзя сделать это через деривацию?

Tim Roberts 08.08.2024 19:10

@TimRoberts Я использовал статические классы только для этого примера. В реальном приложении используются «обычные» классы.

Stefman1987 08.08.2024 19:45

Вам следует хорошо подумать, прежде чем нарушать инкапсуляцию таким образом. Это может легко вызвать ошибки. Тем не менее, бывают редкие случаи, когда это необходимо, например. чтобы обойти ошибку в устаревшей системе, которую вы не можете изменить. Однако для этого вам не нужен ByteBuddy, и я не думаю, что это облегчит задачу. Вы можете сделать это с помощью стандартного отражения. Я закрываю как дубликат.

Matthew Flaschen 09.08.2024 00:54

@MatthewFlaschen Спасибо за ваш комментарий. А теперь, пожалуйста, снова откройте этот вопрос. Этот вопрос о байт-приятеле, но теперь об отражении. Вы видите разницу? Если бы я использовал отражение, я бы задал вопрос об отражении, не так ли? Но мне пришлось создать сложный класс с byte-buddy со множеством различных функций. Я почти сделал это, за исключением настройки частного поля. Итак, это не дубликат. Итак, еще раз, пожалуйста, снова откройте вопрос.

Stefman1987 09.08.2024 07:31

«Мне пришлось создать сложный класс с byte-buddy со множеством различных функций». Это ключевой контекст, о котором не идет речь. Обновите свой вопрос, чтобы объяснить, для чего вы используете ByteBuddy, тогда я снова открою его.

Matthew Flaschen 09.08.2024 15:11

@MatthewFlaschen Я ясно сказал в своем вопросе, что речь шла о байт-приятеле. Это ваша вина, что вы (не знаю почему) решили, что ответом на размышление может стать ответ. Так что обновлять не буду.

Stefman1987 09.08.2024 15:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Byte Buddy создает классы Java, и эти классы должны соответствовать тем же правилам, как если бы вы писали класс вручную. В результате вы не можете установить частное поле из подкласса. Таким образом, вы можете: (а) сделать поле защищенным или (б) переопределить класс, добавив код в класс, который объявляет поле.

Что касается Byte Buddy, проще всего использовать Advice:

class ConstructorAdvice {
  @Advice.OnMethodExit
  static void exit(Advice.Field(value = "foo", readOnly = false) Foo foo) {
    foo = new Foo();
  }
}

Затем вы примените этот совет ко всем соответствующим конструкторам рассматриваемого класса, используя visit.

Другие вопросы по теме