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

时间:2017-01-03 07:36:59

标签: java reflection jvm bytecode

所以我发现了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或其他更高级别的类时,这将如何影响应用程序。这会在JVM中创建内部错误,还是仅仅是JVM数据的克隆并且更改它不会产生任何影响。你可以对这个主题有所了解。非常感谢。

2 个答案:

答案 0 :(得分:3)

您可以将值视为放入箱子中的框中的内容(表示整个对象的箱子,其中的每个框表示一个字段)。反射允许您更改框的内容,但它不允许您更改任何框的形状,也不允许更改框的整体形状。该类的结构在加载后即被修复。

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

答案 1 :(得分:0)

如果班级尚未加载,则仪器可以更改类型。一旦加载了类,更改类型就会困难得多。

使用“不安全”,您可以根据需要访问内存,将int替换为Object引用,但这完全由您自行承担风险。

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