À quoi sert l'opérateur 'instanceof' en Java?


163

À quoi sert l' instanceofopérateur? J'ai vu des trucs comme

if (source instanceof Button) {
    //...
} else {
    //...
}

Mais rien de tout cela n'avait de sens pour moi. J'ai fait mes recherches, mais je n'ai trouvé que des exemples sans aucune explication.


38
Il n'y a rien de mal à poser des questions ici, mais si vous apprenez Java, vous voudrez peut-être obtenir un livre. Tout livre Java décent aurait la réponse à cette question et aux 1000 prochains que vous allez avoir.
President James K. Polk

Un tel opérateur a de nombreuses utilisations spécifiques. Ce serait une question spécifique si elle demandait une explication de l'un des exemples qui n'a pas de sens pour vous.
Raedwald

2
Les réponses ci-dessous sont correctes, mais notez que instanceof est un opérateur surutilisé 9 fois sur 10, il peut être remplacé par une utilisation correcte du polymorphisme (pas toujours, mais souvent)
Richard Tingle

J'irais plus loin que Richard: je n'ai JAMAIS vu d'utilisation valide d'instanceof. Ce n'est utile que pour les hacks rapides en plus d'un code mal conçu. Si vous n'aimez pas la POO, écrivez dans une autre langue (il y en a beaucoup). Dites simplement "non" à instanceof!
Scott Biggs

5
@ScottBiggs Y at - il une bonne alternative à instanceoflors de la substitution equals?
Ben Aaronson

Réponses:


228

instanceofmot-clé est un opérateur binaire utilisé pour tester si un objet (instance) est un sous-type d'un type donné.

Imaginer:

interface Domestic {}
class Animal {}
class Dog extends Animal implements Domestic {}
class Cat extends Animal implements Domestic {}

Imaginez un dog objet , créé avec Object dog = new Dog(), puis:

dog instanceof Domestic // true - Dog implements Domestic
dog instanceof Animal   // true - Dog extends Animal
dog instanceof Dog      // true - Dog is Dog
dog instanceof Object   // true - Object is the parent type of all objects

Cependant, avec Object animal = new Animal();,

animal instanceof Dog // false

parce que Animalc'est un supertype Doget peut-être moins «raffiné».

Et,

dog instanceof Cat // does not even compile!

En effet, ce Dogn'est ni un sous-type ni un supertype de Cat, et il ne l'implémente pas non plus.

Notez que la variable utilisée dogci-dessus est de type Object. Il s'agit de montrer qu'il instanceofs'agit d'une opération d' exécution et nous amène à un cas d'utilisation: réagir différemment en fonction d'un type d'objets à l'exécution .

Choses à noter: expressionThatIsNull instanceof Test faux pour tous les types T.

Bon codage.


14
J'ai juste essayé - Object dog = new Dog(); System.out.println(dog instanceof Cat);. Cela compile très bien et imprime false. Le compilateur n'est pas autorisé à déterminer au moment de la compilation qui dogne peut pas être un Cat (selon les règles du JLS)
Erwin Bolwidt

@ErwinBolwidt Vous avez fait une erreur en essayant cela. Pour tous ceux qui se demandent: la section JLS 15.20.2 est celle que vous recherchez. Pour un exemple de non-travail minimal:boolean b = "foo" instanceof Integer;
Felix S

3
@FelixS Vous devez relire la réponse. La réponse est sur Object indirect = ...; if (indirect instanceof Something). Il ne s'agit pas de ce if (literal instanceof Something)que vous semblez supposer.
Erwin Bolwidt

1
@ErwinBolwidt Oh, c'est vrai, j'ai dû sauter la Object dogpartie. Ma faute!
Felix S

dog instanceof Cat // does not even compile!(parce que c'est une classe). Si Catc'était une interface, elle compilerait.
Hamza Belmellouki

44

C'est un opérateur qui renvoie true si le côté gauche de l'expression est une instance du nom de classe sur le côté droit.

Pensez-y de cette façon. Disons que toutes les maisons de votre pâté de maisons ont été construites à partir des mêmes plans. Dix maisons (objets), un ensemble de plans (définition de classe).

instanceofest un outil utile lorsque vous avez une collection d'objets et que vous n'êtes pas sûr de ce qu'ils sont. Disons que vous avez une collection de contrôles sur un formulaire. Vous voulez lire l'état vérifié de toutes les cases à cocher présentes, mais vous ne pouvez pas demander à un objet ancien ordinaire son état vérifié. Au lieu de cela, vous verriez si chaque objet est une case à cocher, et si c'est le cas, le castez en case à cocher et vérifiez ses propriétés.

if (obj instanceof Checkbox)
{
    Checkbox cb = (Checkbox)obj;
    boolean state = cb.getState();
}

15
C'est-à-dire que l'utilisation instanceofpeut rendre l'abattage sans danger.
Raedwald

29

Comme décrit sur ce site :

L' instanceofopérateur peut être utilisé pour tester si un objet est d'un type spécifique ...

if (objectReference instanceof type)

Un exemple rapide:

String s = "Hello World!"
return s instanceof String;
//result --> true

Cependant, l'application instanceofsur une variable / expression de référence nulle renvoie false.

String s = null;
return s instanceof String;
//result --> false

Puisqu'une sous-classe est un 'type' de sa superclasse, vous pouvez utiliser le instanceofpour vérifier ceci ...

class Parent {
    public Parent() {}
}

class Child extends Parent {
    public Child() {
        super();
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        System.out.println( child instanceof Parent );
    }
}
//result --> true

J'espère que ça aide!


15

Cet opérateur vous permet de déterminer le type d'un objet. Il renvoie une booleanvaleur.

Par exemple

package test;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;

public class instanceoftest
{
    public static void main(String args[])
    {
        Map m=new HashMap();
        System.out.println("Returns a boolean value "+(m instanceof Map));
        System.out.println("Returns a boolean value "+(m instanceof HashMap));
        System.out.println("Returns a boolean value "+(m instanceof Object));
        System.out.println("Returns a boolean value "+(m instanceof Date));
    }
} 

la sortie est:

Returns a boolean value true
Returns a boolean value true
Returns a boolean value true
Returns a boolean value false

14

If sourceest une objectvariable, instanceofest un moyen de vérifier si c'est une Buttonou non.


5

Comme mentionné dans d'autres réponses, l'utilisation typique canonique de instanceofest pour vérifier si un identifiant fait référence à un type plus spécifique. Exemple:

Object someobject = ... some code which gets something that might be a button ...
if (someobject instanceof Button) {
    // then if someobject is in fact a button this block gets executed
} else {
    // otherwise execute this block
}

Notez cependant que le type de l'expression de gauche doit être un type parent de l'expression de droite (voir JLS 15.20.2 et Java Puzzlers, # 50, pp114 ). Par exemple, la compilation des éléments suivants échouera:

public class Test {
    public static void main(String [] args) {
        System.out.println(new Test() instanceof String); // will fail to compile
    }
}

Cela échoue à compiler avec le message:

Test.java:6: error: inconvertible types
        System.out.println(t instanceof String);
                       ^
  required: String
  found:    Test
1 error

Comme Testn'est pas une classe parente de String. OTOH, cela compile parfaitement et imprime falsecomme prévu:

public class Test {
    public static void main(String [] args) {
        Object t = new Test();
        // compiles fine since Object is a parent class to String
        System.out.println(t instanceof String); 
    }
}

Merci d'avoir lié à la spécification!
jpaugh

1
public class Animal{ float age; }

public class Lion extends Animal { int claws;}

public class Jungle {
    public static void main(String args[]) {

        Animal animal = new Animal(); 
        Animal animal2 = new Lion(); 
        Lion lion = new Lion(); 
        Animal animal3 = new Animal(); 
        Lion lion2 = new Animal();   //won't compile (can't reference super class object with sub class reference variable) 

        if(animal instanceof Lion)  //false

        if(animal2 instanceof Lion)  //true

        if(lion insanceof Lion) //true

        if(animal3 instanceof Animal) //true 

    }
}

1

Peut être utilisé comme un raccourci dans le contrôle d'égalité.

Donc ce code

if(ob != null && this.getClass() == ob.getClass) {
}

Peut être écrit comme

if(ob instanceOf ClassA) {
}

1

La plupart des gens ont correctement expliqué le «quoi» de cette question, mais personne n'a expliqué correctement le «comment».

Voici donc une illustration simple:

String s = new String("Hello");
if (s instanceof String) System.out.println("s is instance of String"); // True
if (s instanceof Object) System.out.println("s is instance of Object"); // True
//if (s instanceof StringBuffer) System.out.println("s is instance of StringBuffer"); // Compile error
Object o = (Object)s;
if (o instanceof StringBuffer) System.out.println("o is instance of StringBuffer"); //No error, returns False
else System.out.println("Not an instance of StringBuffer"); // 
if (o instanceof String) System.out.println("o is instance of String"); //True

Les sorties:

s is instance of String
s is instance of Object
Not an instance of StringBuffer
o is instance of String

La raison de l'erreur du compilateur lors de la comparaison savec StringBuffer est bien expliquée dans la documentation :

Vous pouvez l'utiliser pour tester si un objet est une instance d'une classe, une instance d'une sous-classe ou une instance d'une classe qui implémente une interface particulière.

ce qui implique que le LHS doit être une instance de RHS ou d'une classe qui implémente RHS ou étend RHS.

Comment utiliser alors use instanceof?
Étant donné que chaque classe étend Object, la conversion de type LHS en objet fonctionnera toujours en votre faveur:

String s = new String("Hello");
if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //No compiler error now :)
else System.out.println("Not an instance of StringBuffer");

Les sorties:

Not an instance of StringBuffer

Dans le dernier exemple, pourquoi renvoie-t-il "Pas une instance de StringBuffer"? Puisque vous avez tapé s en Object sur LHS et que vous avez vérifié s'il s'agit d'une instance de RHS if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //shouldn't this be true, puisque nous sommes en train de transtyper s en Object?
sofs1

Parce que s est une référence à un objet String (Java emploie un polymorphisme dynamique contrairement à C ++) et String n'est pas une sous-classe de StringBuffer.
sziraqui


0

L'instance de mot-clé est utile lorsque vous souhaitez connaître l'instance d'un objet particulier.

Supposons que vous lancez une exception et que vous avez catch, effectuez une opération personnalisée de somme, puis continuez à nouveau selon votre logique (throws ou journal, etc.)

Exemple: 1) L'utilisateur a créé l'exception personnalisée "InvalidExtensionsException" et la lance selon la logique

2) Maintenant dans catch block catch (Exception e) {exécute une logique de somme si le type d'exception est "InvalidExtensionsException"

InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;

3) Si vous ne vérifiez pas l'instance et le type d'exception est une exception de pointeur Null, votre code sera interrompu.

Donc, votre logique devrait être à l'intérieur de l'instance de if (e instanceof InvalidExtensionsException) {InvalidExtensionsException InvalidException = (InvalidExtensionsException) e; }

L'exemple ci-dessus est une mauvaise pratique de codage.Cependant, cet exemple vous aide à comprendre l'utilisation de l'instance de celui-ci.


0

La meilleure explication est jls . Essayez toujours de vérifier ce que dit la source. Là, vous obtiendrez la meilleure réponse et bien plus encore. Reproduire certaines parties ici:

Le type de l'opérande RelationalExpression de l'opérateur instanceof doit être un type référence ou le type nul; sinon, une erreur de compilation se produit.

Il s'agit d'une erreur de compilation si le ReferenceType mentionné après l'opérateur instanceof ne désigne pas un type de référence réifiable (§4.7).

Si un transtypage (§15.16) de RelationalExpression en ReferenceType est rejeté comme erreur de compilation, alors l'instance d'expression relationnelle produit également une erreur de compilation. Dans une telle situation, le résultat de l'expression instanceof ne pourrait jamais être vrai.


0

L' instanceofopérateur java est utilisé pour tester si l'objet est une instance du type spécifié (classe ou sous-classe ou interface).

L'instance de java est également connue sous le nom de type comparison operatorcar elle compare l'instance avec le type. Il renvoie soit trueou false. Si nous appliquons l' instanceofopérateur avec n'importe quelle variable qui anull valeur, il retourne false.

À partir de JDK 14+ qui comprend JEP 305, nous pouvons également faire de la «correspondance de modèles»instanceof

Les modèles testent essentiellement qu'une valeur a un certain type et peuvent extraire des informations de la valeur lorsqu'elle a le type correspondant. La correspondance de modèles permet une expression plus claire et plus efficace de la logique commune dans un système, à savoir la suppression conditionnelle de composants d'objets.

Avant Java 14

if (obj instanceof String) {
    String str = (String) obj; // need to declare and cast again the object
    .. str.contains(..) ..
}else{
     str = ....
}

Améliorations de Java 14

if (!(obj instanceof String str)) {
    .. str.contains(..) .. // no need to declare str object again with casting
} else {
    .. str....
}

Nous pouvons également combiner le contrôle de type et d'autres conditions ensemble

if (obj instanceof String str && str.length() > 4) {.. str.contains(..) ..}

L'utilisation de la correspondance de motifs dans instanceof devrait réduire le nombre total de transtypages explicites dans les programmes Java.

PS : instanceOfne correspondra que lorsque l'objet n'est pas nul, alors seul il peut être attribué str.


-1
class Test48{
public static void main (String args[]){
Object Obj=new Hello();
//Hello obj=new Hello;
System.out.println(Obj instanceof String);
System.out.println(Obj instanceof Hello);
System.out.println(Obj instanceof Object);
Hello h=null;
System.out.println(h instanceof Hello);
System.out.println(h instanceof Object);
}
}  

1
Ne postez pas uniquement les réponses sur StackOverflow. Veuillez continuer et ajouter une explication.
L. Guthardt

-2

Exemple de code très simple:

If (object1 instanceof Class1) {
   // do something
} else if (object1 instanceof Class2) {
   // do something different
}

Soyez prudent ici. Dans l'exemple ci-dessus, si Class1 est Object, la première comparaison sera toujours vraie. Ainsi, tout comme avec des exceptions, l'ordre hiérarchique est important!


-2

Vous pouvez utiliser Map pour faire une abstraction plus élevée sur l'instance de

private final Map<Class, Consumer<String>> actions = new HashMap<>();

Ensuite, une telle carte lui ajoute une action:

actions.put(String.class, new Consumer<String>() {
        @Override
        public void accept(String s) {
           System.out.println("action for String");       
        }
    };

Ensuite, avec un objet de type inconnu, vous pouvez obtenir une action spécifique de cette carte:

actions.get(someObject).accept(someObject)

-2

L'opérateur instanceof est utilisé pour vérifier si l'objet est une instance du type spécifié. (classe ou sous-classe ou interface).

L'instanceof est également connue sous le nom d'opérateur de comparaison de type car elle compare l'instance avec le type. Il renvoie vrai ou faux.

class Simple1 {  
public static void main(String args[]) {  
Simple1 s=new Simple1();  
System.out.println(s instanceof Simple1); //true  
}  
}  

Si nous appliquons l'opérateur instanceof avec n'importe quelle variable qui a une valeur nulle, il retourne false.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.