2012-02-06 15 views
6

Llamo a un método por reflexión, y su tipo de devolución es genérico. No quiero que el valor de retorno sea nulo, entonces en ese caso quiero asignar un valor predeterminado de ese tipo genérico.Asignar un valor predeterminado a un genérico

Es decir, después de llamando al método de reflexión, me gustaría ejecutar algo como esto:

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"; 
    } 
} 

Pero, por supuesto, si 'resultNotNull == null', no podemos llame a 'resultNotNull.getClass()' sin obtener una excepción.

¿Alguna idea sobre cómo asignar un valor predeterminado según el tipo genérico?

Todo el código sería algo como esto:

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

Respuesta

3

Puede utilizar 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

No obtendría Return Objeto devuelto objeto? Los genéricos se borran en el momento de la compilación. – Pablo

+0

getReturnType() devolverá Object si el tipo de devolución es Object o Generic que devuelve Object. En los ejemplos anteriores sería 'Long' y' String' –

+0

OK, leí mal la pregunta, pensé que quería decir que el método "método" era genérico. – Pablo

0

Por qué su T no podían implementa alguna de las interfaces o ampliar alguna clase base? A continuación, puede llamar a algún método predeterminado estático de T que devuelva el valor predeterminado para la clase dada T. Pros? Encapsulará su código switch justo a la clase correcta.

Por supuesto, sin ninguna interfaz, toda su clase T podría tener algún método como getDefaultValue().

+0

No, no puedo cambiar las clases T para agregar un método 'getDefaultValue()', ni cambiar lo que devuelven. –

Cuestiones relacionadas