2017-01-03 4 views
-1

So entdeckte ich, wie zu Change private static final field using Java reflection eine Weile zurück und habe es verwendet, um letzte Felder mit Reflexion seitdem zu ändern, jedoch habe ich mich dann gefragt, warum ich nicht die gleiche Logik anwenden konnte zu dem Typ für das Feld. Ich kam mitKann Reflexion den deklarierten Typ eines Feldes ändern

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()); 
    } 
} 

Doch dies führte mich bis zu fragen, wie diese eine Anwendung bewirken würde, wenn Sie, sagen wir, den Typ für ein Feld Object gesetzt, wenn es ursprünglich war ein ArrayList oder eine andere höhere Ebene Klasse. Würde dies zu internen Fehlern innerhalb der JVM führen oder wäre dieser Wert einfach ein Klon der JVM-Daten und hätte sich dies geändert, hätte dies keine Auswirkungen. Jedes Licht, das Sie auf das Thema werfen können, wird sehr geschätzt.

+1

kurze antwort: nein. Es ist nicht möglich, den Typ der Variablen zu ändern, und es ist auch nicht möglich, den Bereich zu ändern (z. B. statisch). –

+1

Nur Instrumentation kann dies tun, wenn die JVM dies unterstützt. Die Mainstream-JVMs unterstützen dies überhaupt nicht. – Holger

Antwort

2

Sie können sich Werte als Dinge vorstellen, die Sie in Kästen innerhalb einer Kiste platzieren (die Kiste repräsentiert das ganze Objekt und jedes Kästchen darin repräsentiert ein Feld). Mit Reflection können Sie den Inhalt von Boxen ändern, aber Sie können weder die Form einer Box noch die Gesamtform der Box ändern. Die Struktur der Klasse ist festgelegt, sobald sie geladen ist.

Es gibt Möglichkeiten, es im laufenden Betrieb zu ändern, wie es von einer Datei .class gelesen wird. Dieser Prozess wird als Bytecode Weben bezeichnet. Unnötig zu sagen, es ist etwas komplizierter (wenn Sie zum Beispiel eine Methode so ändern, dass sie einen Int anstelle eines Long-Wertes annimmt, müssen Sie auch alle Call-Sites dieser Methode so ändern, dass sie Int anstelle von Long übergeben) .

0

Die Instrumentierung kann den Typ ändern, sofern die Klasse noch nicht geladen wurde. Sobald eine Klasse geladen wurde, ist das Ändern des Typs viel schwieriger.

Mit Unsafe können Sie auf den Speicher zugreifen, wie Sie wünschen, tauschen int für Object Referenz, aber das ist völlig auf eigenes Risiko verwendet.

Hinweis: Wenn Sie den Typ der Referenz von List zu Object zur Laufzeit ändern, wird der Typ des referenzierten tatsächlichen Objekts nicht geändert.

Verwandte Themen