#byte-buddy
#byte-buddy
Вопрос:
Использование ByteBuddy как я могу создать перечисление с помощью таких конструкторов, как этот :
public enum EnumConstructorSample {
STATE1(10),
STATE2(15);
public int count;
EnumConstructorSample(int count){
this.count = count;
}
}
Я попробовал этот код, и он выдает ошибку.
Class enumClass = new ByteBuddy().makeEnumeration("STATE1", "STATE2")
.name("DynamicEnum")
.defineConstructor(Visibility.PACKAGE_PRIVATE)
.withParameters(int.class)
.intercept(FixedValue.value(1))
.make()
.load(EnumWithConstructor.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
System.out.println(enumClass.getDeclaredConstructors()[0]);
Это ошибка, и она происходит в enumClass.getDeclaredConstructors()
Exception in thread "main" java.lang.VerifyError: Constructor must call super() or this() before return
Exception Details:
Location:
DynamicEnum.<init>(I)V @2: return
Reason:
Error exists in the bytecode
Bytecode:
0x0000000: 0457 b1
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getDeclaredConstructors(Class.java:2020)
at EnumWithConstructor.main(EnumWithConstructor.java:19)
Ответ №1:
Для конструкторов требуется вызвать метод super в конструкторе. Для перечислений вам нужно будет вызвать Enum(String, int)
конструктор. Вы можете реализовать это с помощью MethodCall.invoke(...).onSuper()
.
Если вы хотите добиться этого, я бы рекомендовал вам выполнить подкласс Enum
вручную, поскольку в противном случае вы бы определили несколько конструкторов для создаваемого вами перечисления, где Byte Buddy будет вызывать свой собственный конструктор перечислений, а все поля будут иметь значение по умолчанию.
Скорее, реализуйте метод и возвращайте значение на основе его имени. Вы можете, например, использовать a MethodDelegation
, а затем использовать @This Enum<?> val
инъекцию, где вы переключаете имя, чтобы вернуть правильное значение, как если бы оно было сохранено в поле.
Комментарии:
1. Java не позволяет расширять класс
Enum
. С помощьюMethodCall.invoke(Enum.class.getConstructor(...)).with(...)
я смог создать перечисление, но тогда Java не позволяетEnum
создавать s с помощью отражения. Проблема в том, что ByteBuddy не распознает этот новый конструктор и не создает экземпляры Enum, как раньше. Есть ли способ вызвать мой перехватчик после завершения выполнения обычного конструктора Enum, чтобы я просто инициализировал поля?2. Да, вы также можете определить поля и, например, использовать
TypeInitializer
илиLoadedTypeInitializer
.