2017-01-03 79 views
-1

所以我发现如何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数据的一个副本,并且改变它不会起作用。任何你可以解决这个问题的光是非常感谢。

+1

简答:不。无法更改变量的类型,也无法更改其范围(例如,使其变为静态)。 –

+1

只有JVM支持,Instrumentation才能执行此操作。主流JVM根本不支持这一点。 – Holger

回答

2

您可以将值放在箱子内的框中(表示整个对象的箱子以及表示一个域的每个箱子)。反射可让您更改框的内容,但它不会让您更改任何框的形状,也不会更改框的整体形状。该类的结构在加载后会被修复。

尽管如此,在从.class文件中读取文件时,仍可以随时对其进行更改。该过程称为字节码编织。不用说,这有点麻烦(例如,如果你改变一个方法来接受一个int而不是一个long,那么你也需要改变该方法的所有调用位置以传入一个int而不是一个long) 。

0

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

使用不安全,您可以随意访问内存,交换intObject参考,但这完全是在使用您自己的风险。

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