2015-09-22 18 views
13

ho 2 classi: Father e ChildImpostare valore del campo privato con la riflessione

public class Father implements Serializable, JSONInterface { 

    private String a_field; 

    //setter and getter here 

} 

public class Child extends Father { 
    //empty class 
} 

Con riflessione voglio impostare a_field in Child classe:

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

ma ho un'eccezione:

Eccezione nel thread "main" java.lang.NoSuchFieldException: a_field

Ma se provo:

Child child = new Child(); 
child.setA_field("123"); 

funziona.

Usando metodo setter Ho lo stesso problema:

method = cc.getClass().getMethod("setA_field"); 
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" }); 
+2

È necessario ottenere la superclasse della classe prima, prima che essendo in grado di acces campo. [un'altra domanda SO] (http: // StackOverflow.it/questions/3567372/access-to-private-inherited-fields-via-reflection-in-java) – SomeJavaGuy

+1

Il campo non fa parte della classe Child Poiché è privato, non è nemmeno visibile nella classe Child. i setter sono pubblici e vengono ereditati, il che significa che possono essere chiamati come se fossero stati dichiarati nella classe Child. – f1sh

+0

Invece di recuperare il campo che è privato, impostarne il valore recuperando il suo setter Metodo –

risposta

-4

Come per la Javadoc di Class.getField (sottolineatura mia):

Restituisce un oggetto campo che riflette il campo membro pubblica specificata di la classe o l'interfaccia rappresentata da questo oggetto di classe.

Questo metodo restituisce solo campi pubblici. Poiché a_field è privato, non verrà trovato.

Ecco un codice di lavoro:

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 
} 

Si noti che ho anche cambiato la vostra linea String str1 = (String) f1.get(cc.getClass()); per String str1 = (String) f1.get(cc); perché è necessario dare l'oggetto del campo, non la classe.


Se si desidera mantenere il vostro campo privato, allora avete bisogno di recuperare il metodo getter/setter e richiamare coloro invece. Il codice che hai dato non funziona perché, per ottenere un metodo, è inoltre necessario specificare che è argomenti, in modo

cc.getClass().getMethod("setA_field"); 

deve essere

cc.getClass().getMethod("setA_field", String.class); 

Ecco un codice di lavoro:

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 
} 
+0

grazie .. ma a_field deve essere privato. In alternativa, posso chiamare il metodo setter? – user1066183

+0

@ user1066183 Ho modificato il mio post. – Tunaki

+0

Grazie, la tua soluzione funziona per me. – user1066183

47

Per accedere a un campo privato è necessario impostare Field::setAccessible su true. Puoi estrarre il campo dalla super classe. Questo codice funziona:

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); 
0

Questo può accedere ai campi privati ​​e, senza dover fare nulla

import org.apache.commons.lang3.reflect.FieldUtils; 
Object value = FieldUtils.readField(entity, fieldName, true); 
Problemi correlati