145 votes

Instanceof Vs getClass( )

Je vois une amélioration de performances en utilisant l'opérateur getClass() et == plutôt que l'opérateur instanceOf.

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("c'est une chaîne de caractères");
} else {
    if (str instanceof Integer) {
        System.out.println("c'est un entier");
    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("c'est une chaîne de caractères avec equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("c'est un entier");
    }
}

System.out.println((System.nanoTime()-starttime));

Est-ce qu'il existe des directives pour savoir quand utiliser getClass() ou instanceOf ?

Dans un scénario donné : je connais les classes exactes à vérifier, c'est-à-dire String, Integer (ce sont des classes finales), etc.

Est-ce que l'utilisation de l'opérateur instanceOf est une mauvaise pratique ?

4 votes

Cela est expliqué dans: stackoverflow.com/questions/596462/….

5 votes

Votre méthode de chronométrage cause des retards artificiels et produit des résultats temporels incorrects. Inversez l'ordre des vérifications que vous effectuez et vous verrez que la première vérification que vous faites (soit == ou instanceof) sera toujours plus longue. Je suppose que ce sont les println()s. Vous ne devriez jamais inclure ce genre de choses dans votre bloc de chronométrage.

3 votes

Juste un commentaire à part, pour comparer les performances, utilisez plusieurs itérations du cycle (par exemple 10000) afin d'améliorer la précision. Une seule invocation n'est pas une bonne mesure.

175voto

Stephen C Points 255558

La raison pour laquelle les performances de instanceof et getClass() == ... sont différentes est qu'ils font des choses différentes.

  • instanceof teste si la référence d'objet du côté gauche (LHS) est une instance du type du côté droit (RHS) ou d'un sous-type.

  • getClass() == ... teste si les types sont identiques.

Donc, la recommandation est d'ignorer le problème de performance et d'utiliser l'alternative qui vous donne la réponse dont vous avez besoin.

Est-ce que l'utilisation de l'opérateur instanceOf est une mauvaise pratique ?

Non nécessairement. L'abus de instanceOf ou de getClass() peut être un "mauvais signe de conception". Si vous n'êtes pas prudent, vous vous retrouvez avec une conception où l'ajout de nouvelles sous-classes nécessite une refonte significative du code. Dans la plupart des situations, l'approche préférée est d'utiliser le polymorphisme.

Cependant, il y a des cas où cela ne représente PAS un "mauvais signe de conception". Par exemple, dans equals(Object) vous devez tester le type réel de l'argument et renvoyer false s'il ne correspond pas. Il est préférable de le faire en utilisant getClass().


Des termes comme "meilleure pratique", "mauvaise pratique", "mauvais signe de conception", "anti-patron" et ainsi de suite devraient être utilisés avec parcimonie et traités avec méfiance. Ils encouragent une pensée en noir et blanc. Il est préférable de faire vos jugements en contexte, plutôt que basés uniquement sur le dogme; par exemple, quelque chose que quelqu'un a dit être une "meilleure pratique". Je recommande à tous de lire No Best Practices si ce n'est pas déjà fait.

49voto

Jon Skeet Points 692016

Voulez-vous faire correspondre une classe exactement, par exemple ne correspondre qu'à FileInputStream au lieu de toute sous-classe de FileInputStream ? Si oui, utilisez getClass() et ==. Je ferais généralement cela dans un equals, afin qu'une instance de X ne soit pas considérée égale à une instance d'une sous-classe de X - sinon vous pouvez rencontrer des problèmes de symétrie délicats. D'un autre côté, c'est généralement plus utile pour comparer que deux objets sont de la même classe que d'une classe spécifique.

Sinon, utilisez instanceof. Notez qu'avec getClass() vous devrez vous assurer d'avoir une référence non nulle pour commencer, sinon vous obtiendrez une NullPointerException, alors que instanceof renverra simplement false si le premier opérande est nul.

Personnellement, je dirais que instanceof est plus idiomatique - mais utiliser n'importe lequel d'entre eux de manière extensive est souvent un signe de mauvaise conception.

18voto

Andy Dingfelder Points 365

Je sais que cela fait un moment que cette question a été posée, mais j'ai appris une alternative hier

Nous savons tous que vous pouvez faire :

if(o instanceof String) {   // etc

mais que faire si vous ne savez pas exactement de quel type de classe il doit s'agir ? vous ne pouvez pas le faire de manière générique :

if(o instanceof .getClass()) {   

car cela donne une erreur de compilation.
À la place, voici une alternative - isAssignableFrom()

Par exemple :

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}

12 votes

Ne pas utiliser isAssignableFrom. La manière correcte d'écrire o instanceof String en utilisant la réflexion est String.getClass().isInstance(o). Le javadoc le dit même : Cette méthode est l'équivalent dynamique de l'opérateur instanceof du langage Java.

3voto

Saurav Sahu Points 6098

GetClass() a la restriction que les objets ne sont égaux qu'à d'autres objets de la même classe, du même type d'exécution, comme illustré dans la sortie du code ci-dessous :

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Différents résultats de retour de getClass() avec subClassInstance et parentClassInstance");
        }
    }
}

Résultats:

SubClass extends ParentClass. subClassInstance is instanceof ParentClass.

Différents résultats de retour de getClass() avec subClassInstance et parentClassInstance.

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