2012-09-21 6 views
7

Ho un codice che accetta un nome di classe fornito esternamente e deve creare un'istanza che implementa un'interfaccia, chiamiamolo Foo.Trasmissione non selezionata quando si limita il parametro generico alla classe <?>

Come parte di questo processo, mi piacerebbe avere la seguente funzione:

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

Ciò si traduce, ovviamente, in un avvertimento senza controllo, in quanto è veramente pericoloso - il chiamante potrebbe aver richiesto "java.lang . Lungo "per tutto ciò che sappiamo. Alla fine mi piacerebbe che questo metodo garantisse che se non si lancia, allora il reso Class rappresenta un'implementazione Foo.

Il mio migliore soluzione attuale è questa:

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

C'è un modo migliore di fare questo? C'è un modo per farlo che non richiede la soppressione esplicita dell'avviso?

+3

'Classe 'potrebbe essere migliore. –

+1

Mi chiedevo inizialmente, ma sostituendo 'Classe ' con 'Classe 'ha esattamente lo stesso problema. – Martin

+0

Non sto dicendo che sistemerà nulla, ma io _am_ sto dicendo che è più preciso. –

risposta

6

Class.asSubclass:

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

Se la classe richiesta non è una sottoclasse di Foo (o si Foo), si otterrà un ClassCastException. In altre parole, fa praticamente la stessa cosa che fa la tua soluzione.

+0

Grazie! Esattamente quello che stavo cercando. – Martin

Problemi correlati