2012-02-06 4 views
6

Sto chiamando un metodo per la riflessione e il suo tipo restituito è generico. Non voglio che il valore restituito sia nullo, quindi in questo caso desidero assegnare un valore predefinito di tale tipo generico.Assegnazione di un valore predefinito ad un generico

Cioè, dopo chiamare il metodo per riflessione, mi piacerebbe per eseguire qualcosa di simile:

T resultNotNull = (T) reflectionMethodThatCanReturnNull.invoke(anObject); 
// If it's null, let's assign something assignable. 
if (resultNotNull == null) { 
    if (resultNotNull.getClass().isAssignableFrom(Long.class)) { 
     resultNotNull = (T) Long.valueOf(-1); 
    } else if (resultNotNull.getClass().isAssignableFrom(String.class)) { 
     resultNotNull = (T) "NOTHING"; 
    } 
} 

Ma, naturalmente, se 'resultNotNull == null', non possiamo chiama 'resultNotNull.getClass()' senza ottenere un'eccezione.

Qualche idea su come assegnare un valore predefinito in base al tipo generico?

L'intero codice sarebbe qualcosa di simile:

public class ReflectionTest { 
    public class Class1ok { 
     public Long method() { return Long.valueOf(1); } 
    } 
    public class Class1null { 
     public Long method() { return null; } // It returns null 
    } 
    public class Class2ok { 
     public String method() { return "SOMETHING"; } 
    } 

    public static void main(String[] args) { 
     ReflectionTest test = new ReflectionTest(); 

     Long notNullValue1 
      = test.methodReturnNotNull(Class1ok.class); // 1 
     Long notNullValue2 
      = test.methodReturnNotNull(Class1null.class); // -1, not null 
     String notNullValue3 
      = test.methodReturnNotNull(Class2ok.class); // "SOMETHING" 
    } 

    public <T> T methodReturnNotNull(Class theClass) { 
     T resultNotNull = null; 
     try { 
      Object theObject = theClass.newInstance(); 
      Method methodThatCanReturnNull = theClass.getMethod("method"); 
      resultNotNull = (T) methodThatCanReturnNull.invoke(theObject); 
     } catch (Exception e) { 
      // Meh. 
     } 

     // If it's null, assign something assignable. 
     if (resultNotNull == null) { 
      if (resultNotNull.getClass().isAssignableFrom(Long.class)) { 
       resultNotNull = (T) Long.valueOf(-1); 
      } else if (resultNotNull.getClass().isAssignableFrom(String.class)) { 
       resultNotNull = (T) "NOTHING"; 
      } 
     } 
     return resultNotNull; 
    } 
} 

risposta

3

È possibile utilizzare getReturnType();

private static final Map<Class, Object> replacementForNull = new HashMap<>(); 
static { 
    replacementForNull.put(String.class, "NOTHING"); 
    replacementForNull.put(Long.class, 1L); 
} 


Method reflectionMethodThatCanReturnNull = ... 
T resultNotNull = (T) reflectionMethodThatCanReturnNull.invoke(anObject); 
// If it's null, let's assign something assignable. 
if (resultNotNull == null) { 
    Class returnType = reflectionMethodThatCanReturnNull.getReturnType(); 
    resultNotNull = replacementForNull.get(returnType); 
} 
+0

Non getReturnType() restituisce l'oggetto? I generici vengono cancellati al momento della compilazione. – Pablo

+0

getReturnType() restituirà Object se il tipo restituito è Object o Generic che restituisce Object. Negli esempi sopra sarebbe 'Long' e' String' –

+0

OK, ho letto male la domanda, pensavo volesse dire che il metodo "metodo" era generico. – Pablo

0

Perché il vostro T non potevano implementa alcune interfaccia o estendere alcune classe di base? Quindi è possibile chiamare un metodo statico predefinito da T che restituisce il valore predefinito per la classe data T. Professionisti? Incapsulerà il tuo codice switch solo per la classe giusta.

Ovviamente, senza alcuna interfaccia, tutta la tua possibile classe T potrebbe avere solo un metodo come getDefaultValue().

+0

No, non posso cambiare le classi T per aggiungere un metodo 'getDefaultValue()', né cambiare ciò che restituiscono. –