web-dev-qa-db-fra.com

Pourquoi une variable "Class" ne peut-elle pas être transmise à instanceof?

Pourquoi ce code ne compile-t-il pas?

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

Pourquoi je ne peux pas passer une variable de classe à instanceof?

78
eric2323223

L'opérateur instanceof fonctionne sur les types de référence, comme Integer, et non sur les objets, comme new Integer(213). Vous voulez probablement quelque chose comme

clazz.isInstance(obj)

Note latérale: votre code sera plus concis si vous écrivez

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

Je ne sais pas vraiment si vous avez besoin d'une méthode, cependant.

121
Robert Munteanu

instanceof ne peut être utilisé qu'avec des noms de classe explicites (indiqués lors de la compilation). Pour effectuer une vérification runtime, vous devez:

clazz.isInstance(obj)

Cela a un petit avantage sur clazz.isAssignableFrom(..) car il traite mieux le cas obj == null.

12
Eyal Schneider

Premièrement, instanceof requiert que l'opérande de droite soit une classe réelle (par exemple obj instanceof Object ou obj instanceof Integer) et non une variable de type Class. Deuxièmement, vous avez fait une erreur de débutant assez courante que vous ne devriez vraiment pas faire ... le modèle suivant:

si ( expression_conditionnelle ) {
 retourne vrai; 
} sinon {
 retourne faux; 
} 

Ce qui précède peut être refactorisé en:

revenir expression_conditionnelle; 

Vous devez toujours effectuer cette refactorisation, car elle élimine une instruction redondante if ... else. De même, l'expression return conditional_expression ? true : false; est refactorable au même résultat.

3

Comme d'autres l'ont mentionné, vous ne pouvez pas passer une variable de classe à instanceof car une variable de classe référence une instance d'un objet , tandis que la droite la main de instanceof doit être de type . Autrement dit, instanceof ne signifie pas "y est une instance de l'objet x", cela signifie "y est une instance de type X". Si vous ne connaissez pas la différence entre un objet et un type, considérez:

Object o = new Object();

Ici, le type est Object et o est une référence à l'instance de l'objet avec ce type. Donc:

if(o instanceof Object)

est valide mais

if(o instanceof o)

n'est pas parce que o sur le côté droit est un objet, pas un type.

Plus spécifique à votre cas, une instance de classe n'est pas un type, c'est un objet (qui est créé pour vous par la JVM). Dans votre méthode, Class est un type, mais clazz est un objet (enfin, une référence à un objet)

Ce dont vous avez besoin est un moyen de comparer un objet à un objet de classe. Il s'avère que ceci est populaire, donc cela vous est fourni comme méthode de l'objet de classe: isInstance().

Voici le document Java Doc pour isInstance, qui explique mieux cela:

public boolean isInstance(Object obj)

Détermine si l'objet spécifié est compatible avec l'affectation avec l'objet représenté par cette classe. Cette méthode est l'équivalent dynamique de l'opérateur instanceof du langage Java. La méthode renvoie true si l'argument Object spécifié n'est pas nul et peut être converti en le type de référence représenté par cet objet Class sans augmenter une ClassCastException. Elle renvoie false dans le cas contraire.

Plus précisément, si cet objet Class représente une classe déclarée, cette méthode renvoie true si l'argument Object spécifié est une instance de la classe représentée (ou de l'une de ses sous-classes); elle renvoie false sinon. Si cet objet Class représente une classe de tableau, cette méthode renvoie true si l'argument Object spécifié peut être converti en un objet de la classe de tableau par une conversion d'identité ou par une conversion de référence élargie; elle renvoie false sinon. Si cet objet Class représente une interface, cette méthode renvoie true si la classe ou toute superclasse de l'argument Object spécifié implémente cette interface; elle renvoie false sinon. Si cet objet Class représente un type primitif, cette méthode renvoie false.

Paramètres: obj - l'objet à vérifier
Renvoie: true si obj est une instance de cette classe
Depuis: JDK1.1

3
Rick Hanlon II