我被这个问题困扰了近三个月,但自己无法解决。我希望这是可能的。我试图用我自己的自定义实体类注入(inject)此代码,该类很难访问,因为该类是静态的并且该字段是最终的。不知何故,我不确定泛型类型在访问它时是否存在问题。
public class EntityTypes<T extends Entity> {
private final EntityTypes.b<T> aZ;
[some code here]
public interface b<T extends Entity> {
T create(EntityTypes<T> entitytypes, World world);
}
public static class a<T extends Entity> {
private final EntityTypes.b<T> a;
[more code here]
}
}
到目前为止,我尝试使用反射,但我不断得到:
java.lang.IllegalArgumentException: Can not set net.server.EntityTypes$b field net.server.EntityTypes$a.a to net.server.EntityTypes
这是我的运行代码:
// works
ReflectionUtils.setFinal(EntityTypes.class, EntityTypes.VILLAGER, "aZ", (EntityTypes.b<CustomVillager>) CustomVillager::new);
// while this does not work!
ReflectionUtils.setFinal(EntityTypes.a.class, EntityTypes.VILLAGER, "a", (EntityTypes.b<CustomVillager>) CustomVillager::new);
public class ReflectionUtils {
// Does only work on Java 12 and above!!
public static void setFinal(Class cls, Object obj, String fieldName, Object value) {
try {
Field field = cls.getDeclaredField(fieldName);
FieldHelper.makeNonFinal(field);
field.setAccessible(true);
field.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
// For Java 12 final field injection
// https://stackoverflow.com/questions/56039341/get-declared-fields-of-java-lang-reflect-fields-in-jdk12/
public final static class FieldHelper {
private static final VarHandle MODIFIERS;
static {
try {
var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
public static void makeNonFinal(Field field) {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
MODIFIERS.set(field, mods & ~Modifier.FINAL);
}
}
}
}
public class CustomVillager extends EntityVillager {
public CustomVillager(EntityTypes<? extends CustomVillager> entityTypes, World world) {
super(entityTypes, world);
}
}
最佳答案
您收到的异常意味着 Field
对象表示的类中的字段与您尝试设置它的对象的类不同。因此,在您的 setFinal()
方法中,您获得一个 Field
对象,表示类 cls
上名为 fieldName
的字段,然后尝试在对象 obj
上设置该字段。这意味着作为 obj
传入的对象必须是类 cls
的实例,否则它将无法工作。
查看调用setFinal()
的两行,第一行获取EntityTypes
类中的字段aZ
;该字段仅存在于 EntityTypes 实例上。第二个 setFinal()
调用获取 EntityTypes.a
类中的字段 a
;该字段仅存在于 EntityTypes.a 的实例上。您尝试在 EntityTypes.VILLAGER 上设置这两个字段。您尚未显示声明或初始化 EntityTypes.VILLAGER
的代码,因此我们不知道它是什么,但是只有当 EntityTypes.VILLAGER
既是 EntityTypes
的实例又是 EntityTypes.a
的实例时,这两行代码才会起作用,这是不可能的(因为它们都是类,都不是另一个的子类,并且 Java 没有类的双重继承)。所以这两行之一肯定是错误的。
关于java - 如何使用泛型类型访问静态内部类中的字段? (非常困难),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035247/