java - 如何使用泛型类型访问静态内部类中的字段? (非常困难)

标签 java generics reflection

我被这个问题困扰了近三个月,但自己无法解决。我希望这是可能的。我试图用我自己的自定义实体类注入(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/

相关文章:

generics - 如何使用 Scala 的 Manifest 类在运行时实例化已删除的类?

java - javadoc 在 `Class.getDeclaredMethod` 上的混淆

java - 在java中使用反射查找复合类的所有属性

java - 基于物联网的家庭自动化系统(如 Alexa)中使用的设计模式

java - 如何使用HtmlUnit java上传&lt;input multiple>中的多个文件

java - 如何确定 Java 中泛型字段的类型?

java - 二维数组和泛型问题 (Java)

java - Android Fragment 不接受 setcontentview

java - Java 中的进度条

Java 持久性标准;将 Expression<Timestamp> 转换为 Expression<Long>?