反射可以改变字段的声明类型吗

Can reflection change the declared type of a field

所以我不久前发现了如何 Change private static final field using Java reflection 并且从那以后一直使用它来修改带有反射的最终字段,但是我开始想知道为什么我不能对类型应用相同的逻辑对于领域。我想到了

public static void changeFieldType(Field field, Class newType){
    try {
        Field typeField = Field.class.getDeclaredField("type");
        typeField.setAccessible(true);
        typeField.set(field, newType);
    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
        LogUtil.printErr("Failed to edit field type for " + field.getName());
    }
}

然而,这让我想知道如果您将一个字段的类型设置为 Object,而它最初是 ArrayList 或其他更高级别 class。这会在 JVM 中产生内部错误,还是这个值只是 JVM 数据的克隆并且更改它不会有任何效果。非常感谢您对这个主题的任何启发。

您可以将值视为您放入板条箱内的盒子中的东西(板条箱代表整个对象,其中的每个盒子代表一个字段)。反射可以让你改变盒子的内容,但它不能让你改变任何盒子的形状,也不能改变箱子的整体形状。 class'结构一旦加载就固定了。

不过,当它从 .class 文件中读取时,有一些方法可以即时更改它。该过程称为字节码编织。不用说,它有点棘手(例如,如果您将方法更改为采用 int 而不是 long,那么您还需要更改该方法的所有调用站点以传入 int 而不是 long) .

如果 class 尚未加载,检测可以更改类型。一旦 class 被载入,改变类型就更难了。

使用 Unsafe,您可以随意访问内存,将 int 换成 Object 引用,但这完全由您自己承担风险。

注意:在运行时将引用类型从 List 更改为 Object 不会更改引用的实际对象的类型。