2012-11-15 19 views
91

Sto provando a ricevere il valore del campo tramite riflessione. Il problema è che non conosco il tipo di campi e devo decidere mentre ottengo il valore.Valore di campo generico di riflessione generico

risultati questo codice con questa eccezione:

Impossibile impostare java.lang.String campo com .... nomeCampo a java.lang.String

Field field = object.getClass().getDeclaredField(fieldName); 
field.setAccessible(true); 

Class<?> targetType = field.getType(); 
Object objectValue = targetType.newInstance(); 

Object value = field.get(objectValue); 

ho cercato di lanciare, ma io ottenere gli errori di compilazione:

field.get((targetType)objectValue) 

o

targetType objectValue = targetType.newInstance(); 

Come posso fare questo?

+2

Guardando la [API] (http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Field.html), l'argomento per 'field.get()' dovrebbe essere 'object', non' objectValue'. – akaIDIOT

risposta

92

Come risposero prima, si dovrebbe usare:

Object value = field.get(objectInstance); 

Un altro modo, che a volte è preferito, sta chiamando il getter in modo dinamico. codice di esempio:

public static Object runGetter(Field field, BaseValidationObject o) 
{ 
    // MZ: Find the correct method 
    for (Method method : o.getMethods()) 
    { 
     if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3))) 
     { 
      if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase())) 
      { 
       // MZ: Method found, run it 
       try 
       { 
        return method.invoke(o); 
       } 
       catch (IllegalAccessException e) 
       { 
        Logger.fatal("Could not determine method: " + method.getName()); 
       } 
       catch (InvocationTargetException e) 
       { 
        Logger.fatal("Could not determine method: " + method.getName()); 
       } 

      } 
     } 
    } 


    return null; 
} 

anche essere consapevoli che quando la classe eredita da un'altra classe, è necessario determinare in modo ricorsivo il campo. per esempio, per recuperare tutti i campi di una determinata classe;

for (Class<?> c = someClass; c != null; c = c.getSuperclass()) 
    { 
     Field[] fields = c.getDeclaredFields(); 
     for (Field classField : fields) 
     { 
      result.add(classField); 
     } 
    } 
+0

non sembra proprio vero che tu abbia bisogno di scorrere le super classi da solo. C.getFields() o c.getField() cercherà automaticamente il campo su ciascuna interfaccia dell'attrezzo e in modo ricorsivo attraverso tutte le superclassi. Quindi è sufficiente passare a getX da getDeclaredX. –

+0

Infatti, la routine getFields() ti permetterà di recuperare i campi per tutte le super classi e le interfacce, ma solo quelle pubbliche. Di solito, i campi sono resi privati ​​/ protetti e sono esposti tramite getter/setter. – Marius

+0

@Marius, posso sapere qual è il pacchetto è il 'BaseValidationObject'? – randytan

7

Anche se non è davvero chiaro per me quello che stai cercando di raggiungere, ho notato un evidente errore nel codice: Field.get() aspetta l'oggetto che contiene il campo come argomento, non un (possibile) il valore di quel campo. Quindi dovresti avere field.get(object).

Dal momento in cui sembra essere alla ricerca per il valore di campo, è possibile ottenere che, come:

Object objectValue = field.get(object); 

Non c'è bisogno di istanziare il tipo di campo e di creare un certo valore vuoto/default; o forse c'è qualcosa che ho perso.

+0

grazie, è la prima volta che uso il riflesso e l'ho perso. –

76

si dovrebbe passare un oggetto -ottenere metodo del campo, così

Field field = object.getClass().getDeclaredField(fieldName);  
    field.setAccessible(true); 
    Object value = field.get(object); 
+2

conosci il motivo per cui l'oggetto deve essere usato in field.get (oggetto) - il campo stesso proviene da quell'oggetto, perché ne ha bisogno di nuovo!? – serup

+7

@serup No, l'oggetto Field proviene dall'oggetto Class, che non ha alcuna connessione con l'istanza attuale. ('' 'object.getClass()' '' restituirà questo oggetto Class) –

+0

Sì ofcourse - grazie – serup

4

Si chiama ottiene con l'argomento sbagliato.

dovrebbe essere:

Object value = field.get(object); 
15

Io uso le riflessioni nella realizzazione toString() della mia preferenza per vedere i membri ed i valori (semplice ed debugging rapido) di classe.

Il codice semplificato che sto usando:

@Override 
public String toString() { 
    StringBuilder sb = new StringBuilder(); 

    Class<?> thisClass = null; 
    try { 
     thisClass = Class.forName(this.getClass().getName()); 

     Field[] aClassFields = thisClass.getDeclaredFields(); 
     sb.append(this.getClass().getSimpleName() + " [ "); 
     for(Field f : aClassFields){ 
      String fName = f.getName(); 
      sb.append("(" + f.getType() + ") " + fName + " = " + f.get(this) + ", "); 
     } 
     sb.append("]"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return sb.toString(); 
} 

Spero che possa aiutare qualcuno, perché ho anche cercato.

7
Integer typeValue = 0; 
try { 
    Class<Types> types = Types.class; 
    java.lang.reflect.Field field = types.getDeclaredField("Type"); 
    field.setAccessible(true); 
    Object value = field.get(types); 
    typeValue = (Integer) value; 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

Per favore aggiungi una spiegazione al tuo codice. –

Problemi correlati