2012-09-21 17 views
7

Tengo un código que toma un nombre de clase provisto externamente, y necesita construir una instancia que implemente alguna interfaz, llamémoslo Foo.Lanzamiento sin marcar al limitar el parámetro genérico a la Clase <?>

Como parte de este proceso, me gustaría tener la siguiente función:

private static Class<? extends Foo> fooFromClassName(String name) throws ClassNotFoundException { 
    return (Class<? extends Foo>) Class.forName(name); 
} 

Obviamente, esto da lugar a una advertencia sin control, ya que es realmente peligroso - la persona que llama puede haber pedido "java.lang . Largo "por todo lo que sabemos. En última instancia, me gustaría que este método garantice que, si no se lanza, el Class devuelto representa una implementación de Foo.

Mi mejor solución actual es la siguiente:

private static Class<? extends Foo> fooFromClassName(String name) throws ClassNotFoundException { 
    Class<?> impl = Class.forName(name); 
    if (Foo.class.isAssignableFrom(impl)) { 
     @SuppressWarnings("unchecked") 
     Class<? extends Foo> foo = (Class<? extends Foo>) impl; 
     return foo; 
    } else { 
     // Throw something - ClassCastException perhaps. 
    } 
} 

¿Hay una mejor manera de hacer esto? ¿Hay alguna forma de hacerlo que no requiera una supresión explícita de la advertencia?

+3

'Class 'podría ser mejor. –

+1

¿Estaba pensando en eso originalmente, pero reemplazando 'Clase ' con 'Clase 'tiene exactamente el mismo problema. – Martin

+0

No digo que arregle nada, pero estoy diciendo que es más preciso. –

Respuesta

6

Class.asSubclass:

private static Class<? extends Foo> fooFromClassName(String name) throws ... { 
    return Class.forName(name).asSubclass(Foo.class); 
} 

Si la clase requerida no es una subclase de Foo (o Foo sí mismo), que obtendrá un ClassCastException. En otras palabras, hace más o menos lo mismo que tu solución.

+0

¡Gracias! Exactamente lo que buscaba. – Martin

Cuestiones relacionadas