104 votes

Déterminer si une classe implémente une interface en Java

J'ai un Class objet. Je veux déterminer si le type que le Class représente l'objet qui implémente une interface spécifique. Je me demandais comment cela pouvait être réalisé ?

J'ai le code suivant. En gros, il s'agit de récupérer un tableau de toutes les classes d'un paquet donné. Je veux ensuite parcourir ce tableau et ajouter les objets de classe qui implémentent une interface à ma carte. Le problème est que l'interface isInstance() prend un objet comme paramètre. Je ne peux pas instancier une interface. Je suis donc un peu perdu dans cette affaire. Avez-vous des idées ?

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

251voto

Flavio Points 5369

Vous devez utiliser isAssignableFrom :

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

18voto

Ankur Points 4371

Vous pouvez utiliser la fonction suivante pour obtenir toutes les interfaces implémentées

Class[] intfs = clazz.getInterfaces();

10voto

Vous pouvez utiliser class.getInterfaces() et vérifie ensuite si la classe d'interface s'y trouve.

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

1voto

Manu Navarro Points 372

Vous pouvez également définir l'instance en ajoutant ".class".

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

-1voto

Lu15 Points 136

Une contribution pour toutes les autres réponses si possible ne pas utiliser la réponse la plus récente de méthode isAssignableFrom même la réponse "pas très bonne" consistant à utiliser clazz.getInterfaces() a de meilleures performances que isAssignableFrom .

Une erreur courante pour les développeurs, lorsqu'ils cherchent une réponse à la question du PO, est de préférer isAssignableFrom lorsqu'une instance est disponible, à tort :

if (IMyInterface.isAssignableFrom(myObject.getClass())) {
    ...

Dans la mesure du possible, utilisez IMyInterface.class.isInstance o instanceof car les deux ont de bien meilleures performances. Bien sûr, comme l'a dit l'OP, ils ont l'inconvénient que vous devez avoir une instance et pas seulement l'icône class .

if (IMyInterface.class.isInstance(myObject)) {
    ...
if (myObject instanceof IMyInterface) { // +0.2% slower than `isInstance` (*see benchmark)
    ...

Une solution encore plus rapide, mais moche, consisterait à stocker un fichier statique Set avec toutes les classes "valides" au lieu de les vérifier, cette solution peu glorieuse n'est à privilégier que lorsque vous devez tester beaucoup de classes, car ses performances sont supérieures à celles de toutes les autres approches pour l'analyse directe. class vérifier.

public static final Set<Class<?>> UGLY_SET = Stream.of(MyClass1.class, MyClass2.class, MyClass3.class).collect(Collectors.toCollection(HashSet::new));
if (UGLY_SET.contains(MyClass)) {
    ...

(*) JMH Indice de référence pour +0,2 %.

Veuillez visiter cette réponse des utilisateurs @JBE , @Yura et @aleksandr-dubinsky, crédits pour eux. De plus, il y a beaucoup de détails dans cette réponse pour que les résultats du benchmark ne soient pas valides, alors je vous invite à y jeter un coup d'œil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X