Determina se una classe implementa un'interfaccia in Java


92

Ho un Classoggetto. Voglio determinare se il tipo che l' Classoggetto rappresenta implementa un'interfaccia specifica. Mi chiedevo come si potesse ottenere questo risultato?

Ho il codice seguente. Fondamentalmente ciò che fa è ottenere un array di tutte le classi in un pacchetto specificato. Quindi voglio passare attraverso l'array e aggiungere gli oggetti Class che implementano un'interfaccia alla mia mappa. Il problema è che isInstance()prende un oggetto come parametro. Non riesco a creare un'istanza di un'interfaccia. Quindi sono un po 'in perdita con questo. Qualche idea?

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

Risposte:


215

Dovresti usare isAssignableFrom:

if (YourInterface.class.isAssignableFrom(clazz)) {
    ...
}

Funziona se il progetto è lo stesso. Ma se copi il codice dell'interfaccia 1: 1, crei un nuovo progetto e jar, quindi provi a caricare quel jar come plugin, la chiamata restituirà false. Il confronto per nome poi "funziona", come ha scritto Roddy. Ma non ho idea di come verificarlo nel modo in cui Java alla fine verifica la compatibilità. Per nome è un approccio sporco. Il tuo va bene, ovviamente, se il progetto è lo stesso. ................ FORSE Sto sbagliando: creo un'istanza URLClassLoader per il file del plugin e la carico in questo modo. Forse dovrei provare un programma di caricamento classi diverso.
Presidente Dreamspace

4
Stai riscontrando problemi di caricamento della classe. Se carichi la stessa classe due volte con diversi programmi di caricamento classi, le due Classistanze non saranno compatibili. Potresti vedere errori come java.lang.ClassCastException: com.my.CustomClass cannot be cast to com.my.CustomClasso qualcosa di altrettanto inspiegabile.
Flavio

Ormai ho provato vari approcci e alla fine si è scoperto che il problema principale che avevo era questo: mentre l'interfaccia nel mio plugin e il progetto principale erano identici, non erano nello stesso posto, quindi lo spazio dei nomi / indirizzo era un altro. A proposito, ora sto usando: myClassLoader = new URLClassLoader(new URL[] { candidateFile.toURI().toURL() }, LoadedPlugin.class.getClassLoader());and classToLoad = Class.forName("com.blablabla.plugin.Main", true, myClassLoader);and instance = (MyIntf) classToLoad.newInstance();Works like a charm.
Presidente del Dreamspace

17

puoi usare la seguente funzione per ottenere tutte le interfacce implementate

Class[] intfs = clazz.getInterfaces();

10

Puoi usare class.getInterfaces()e poi controllare per vedere se la classe di interfaccia è lì.

Class someInterface; // the interface you want to check for 
Class x; // 
Class[] interfaces = x.getInterfaces();

for (Class i : interfaces) {
    if (i.toString().equals(someInterface.toString()) {
        // if this is true, the class implements the interface you're looking for
    }
}

Questo approccio tecnicamente funzionerà, ma l'approccio molto più semplice e pulito è quello di utilizzare isAssignableFromcome menziona Flavio.
jwj

Sì, è vero, anche se la tua risposta è stata votata più di un paio di volte e ho pensato che sarebbe stato utile aggiungere un po 'di contesto. Sebbene l'utilizzo isAssignableFromsia probabilmente preferibile, potrebbero esserci casi in cui è necessario eseguire la scansione dell'elenco di interfacce implementate da una classe esaminando i nomi.
jwj

Questo in realtà non funziona, getInterfaces () funziona solo se la classe implementa direttamente l'interfaccia, se una superclasse implementa l'interfaccia, o una super interfaccia la estende, quell'interfaccia non verrà restituita da getInterfaces (). È necessario attraversare l'albero di tutte le super classi e interfacce per ottenere tutte le interfacce implementate dalla classe.
James Roper,

Ma non era questa la domanda.
Roddy of the Frozen Peas

1

Puoi anche impostare l'istanza aggiungendo ".class"

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(Interface.class.isAssignableFrom(clazz))
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

2
Per chiunque stia guardando questo approccio, si prega di considerare la risposta di Flavio. Si noti che il codice in questo esempio fa alcune cose che potrebbero non avere un senso immediato: ClassUtilsnon fa parte di Java (è in Guava o Spring e altri framework), il termine Interfaceusato sopra si riferisce a un'interfaccia specifica in fase di test ( cioè, non è una parola chiave Java in questo contesto) e lo scopo di retValnon è spiegato o menzionato da nessuna parte.
jwj
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.