Ich habe 2 Klassen: Father
undChild
public class Father implements Serializable, JSONInterface {
private String a_field;
//setter and getter here
}
public class Child extends Father {
//empty class
}
Mit Reflexion möchte ich a_field
in der Child
Klasse setzen:
Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc.getClass());
System.out.println("field: " + str1);
aber ich habe eine ausnahme:
Ausnahme im Thread "main" java.lang.NoSuchFieldException: a_field
Aber wenn ich es versuche:
Child child = new Child();
child.setA_field("123");
Es klappt.
Mit der Setter-Methode habe ich das gleiche Problem:
method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
java
reflection
user1066183
quelle
quelle
Antworten:
Um auf ein privates Feld zuzugreifen, müssen Sie
Field::setAccessible
true festlegen . Sie können das Feld aus der Superklasse ziehen. Dieser Code funktioniert:Class<?> clazz = Child.class; Object cc = clazz.newInstance(); Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field"); f1.setAccessible(true); f1.set(cc, "reflecting on life"); String str1 = (String) f1.get(cc); System.out.println("field: " + str1);
quelle
Verwenden
FieldUtils
von Apache Commons Lang 3 :FieldUtils.writeField(childInstance, "a_field", "Hello", true);
Das
true
erzwingt das Setzen, auch wenn das Feld privat ist .quelle
Dieser kann auch auf private Felder zugreifen, ohne etwas tun zu müssen
import org.apache.commons.lang3.reflect.FieldUtils; Object value = FieldUtils.readField(entity, fieldName, true);
quelle
Kotlin Verison
Holen Sie sich eine private Variable mit den folgenden Erweiterungsfunktionen
fun <T : Any> T.getPrivateProperty(variableName: String): Any? { return javaClass.getDeclaredField(variableName).let { field -> field.isAccessible = true return@let field.get(this) } }
Setzen Sie den Wert der privaten Variablen, um die Variable abzurufen
fun <T : Any> T.setAndReturnPrivateProperty(variableName: String, data: Any): Any? { return javaClass.getDeclaredField(variableName).let { field -> field.isAccessible = true field.set(this, data) return@let field.get(this) } }
Variable Verwendung erhalten:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
Festlegen und Abrufen der variablen Verwendung:
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Java-Version
public class RefUtil { public static Field setFieldValue(Object object, String fieldName, Object valueTobeSet) throws NoSuchFieldException, IllegalAccessException { Field field = getField(object.getClass(), fieldName); field.setAccessible(true); field.set(object, valueTobeSet); return field; } public static Object getPrivateFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException { Field field = getField(object.getClass(), fieldName); field.setAccessible(true); return field.get(object); } private static Field getField(Class mClass, String fieldName) throws NoSuchFieldException { try { return mClass.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { Class superClass = mClass.getSuperclass(); if (superClass == null) { throw e; } else { return getField(superClass, fieldName); } } } }
Legen Sie die Verwendung privater Werte fest
RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
Holen Sie sich private Wertnutzung
Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");
quelle
Sie können Manifolds @Jailbreak für die direkte, typsichere Java-Reflexion verwenden:
@Jailbreak Child child = new Child(); child.a_field = "123;
@Jailbreak
Schaltet die untergeordnete lokale Variable im Compiler für den direkten Zugriff auf alle Mitglieder in freiChild
der Hierarchie frei.Ebenso können Sie die Erweiterungsmethode jailbreak () für die einmalige Verwendung verwenden:
child.jailbreak().a_field = "123";
Über die
jailbreak()
Methode können Sie auf jedes Mitglied inChild
der Hierarchie zugreifen .In beiden Fällen löst der Compiler den Feldzugriff für Sie typsicher wie ein öffentliches Feld auf, während Manifold unter der Haube einen effizienten Reflektionscode für Sie generiert.
Erfahren Sie mehr über Manifold .
quelle
Nach dem Javadoc von
Class.getField
(Schwerpunkt Mine):Diese Methode gibt nur öffentliche Felder zurück. Da
a_field
es privat ist, wird es nicht gefunden.Hier ist ein Arbeitscode:
public class Main { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("Child"); Object cc = clazz.newInstance(); Field f1 = cc.getClass().getField("a_field"); f1.set(cc, "reflecting on life"); String str1 = (String) f1.get(cc); System.out.println("field: " + str1); } } class Father implements Serializable { public String a_field; } class Child extends Father { //empty class }
Beachten Sie, dass ich auch Ihre Zeile
String str1 = (String) f1.get(cc.getClass());
in geändert habe ,String str1 = (String) f1.get(cc);
weil Sie das Objekt des Felds und nicht die Klasse angeben müssen.Wenn Sie Ihr Feld privat halten möchten, müssen Sie die Getter / Setter-Methode abrufen und stattdessen diese aufrufen. Der von Ihnen angegebene Code funktioniert nicht, da Sie zum Abrufen einer Methode auch deren Argumente angeben müssen
cc.getClass().getMethod("setA_field");
muss sein
cc.getClass().getMethod("setA_field", String.class);
Hier ist ein Arbeitscode:
public class Main { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("Child"); Object cc = clazz.newInstance(); cc.getClass().getMethod("setA_field", String.class).invoke(cc, "aaaaaaaaaaaaaa"); String str1 = (String) cc.getClass().getMethod("getA_field").invoke(cc); System.out.println("field: " + str1); } } class Father implements Serializable { private String a_field; public String getA_field() { return a_field; } public void setA_field(String a_field) { this.a_field = a_field; } } class Child extends Father { //empty class }
quelle