Wofür wird der Operator 'instanceof' in Java verwendet?


163

Wofür wird der instanceofOperator verwendet? Ich habe Sachen wie gesehen

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

Aber nichts davon ergab für mich einen Sinn. Ich habe meine Nachforschungen angestellt, aber nur Beispiele ohne Erklärungen gefunden.


38
Es ist nichts Falsches daran, hier Fragen zu stellen, aber wenn Sie Java lernen, möchten Sie vielleicht ein Buch bekommen. Jedes anständige Java-Buch hätte die Antwort auf diese Frage und die nächsten 1000, die Sie haben werden.
Präsident James K. Polk

Ein solcher Bediener hat viele spezifische Verwendungszwecke. Dies wäre eine spezielle Frage, wenn eine Erklärung für eines der Beispiele angefordert würde, die für Sie keinen Sinn ergeben.
Raedwald

2
Die Antworten unten sind korrekt, beachten Sie jedoch, dass instanceof ein überstrapazierter Operator ist, der 9 von 10 Mal verwendet wird und durch eine ordnungsgemäße Verwendung des Polymorphismus (nicht immer, aber häufig) ersetzt werden kann
Richard Tingle,

Ich würde noch einen Schritt weiter gehen als Richard: Ich habe NIE eine gültige Verwendung von instanceof gesehen. Es ist nur nützlich für schnelle Hacks über schlecht gestalteten Code. Wenn Sie OOP nicht mögen, schreiben Sie in einer anderen Sprache (es gibt viele). Sagen Sie einfach "Nein" zu instanceof!
Scott Biggs

5
@ScottBiggs Gibt es eine gute Alternative zum instanceofÜberschreiben equals?
Ben Aaronson

Antworten:


228

instanceofDas Schlüsselwort ist ein binärer Operator , mit dem getestet wird, ob ein Objekt (eine Instanz) ein Subtyp eines bestimmten Typs ist.

Vorstellen:

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

Stellen Sie sich ein dog Objekt vor , das erstellt wurde mit Object dog = new Dog():

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

Mit Object animal = new Animal();,

animal instanceof Dog // false

weil Animalist ein Supertyp von Dogund möglicherweise weniger "verfeinert".

Und,

dog instanceof Cat // does not even compile!

Dies liegt daran, dass Doges sich weder um einen Subtyp noch um einen Supertyp Cathandelt und dieser auch nicht implementiert wird.

Beachten Sie, dass die oben verwendete Variable dogvom Typ ist Object. Dies soll zeigen, dass instanceofes sich um eine Laufzeitoperation handelt , und bringt uns zu einem Anwendungsfall: Je nach Objekttyp zur Laufzeit unterschiedlich zu reagieren .

Dinge zu beachten: expressionThatIsNull instanceof Tist für alle Typen falsch T.

Viel Spaß beim Codieren.


14
Ich habe es gerade versucht - Object dog = new Dog(); System.out.println(dog instanceof Cat);. Dies kompiliert gut und druckt false. Der Compiler darf zur Kompilierungszeit nicht feststellen, dass es dogsich nicht um eine Katze handeln kann (gemäß den Regeln in der JLS)
Erwin Bolwidt,

@ErwinBolwidt Sie haben einen Fehler gemacht, als Sie das versucht haben. Für alle, die sich fragen: JLS Abschnitt 15.20.2 ist derjenige, den Sie suchen. Für ein minimales nicht funktionierendes Beispiel:boolean b = "foo" instanceof Integer;
Felix S

3
@FelixS Sie müssen die Antwort erneut lesen. Die Antwort ist ungefähr Object indirect = ...; if (indirect instanceof Something). Es geht nicht darum, if (literal instanceof Something)wie Sie annehmen.
Erwin Bolwidt

1
@ErwinBolwidt Oh, richtig, ich muss das Object dogTeil übersprungen haben . Mein Fehler!
Felix S

dog instanceof Cat // does not even compile!(weil es eine Klasse ist). Wenn Cateine Schnittstelle wäre, würde sie kompiliert.
Hamza Belmellouki

44

Es ist ein Operator, der true zurückgibt, wenn die linke Seite des Ausdrucks eine Instanz des Klassennamens auf der rechten Seite ist.

Denken Sie so darüber nach. Angenommen, alle Häuser in Ihrem Block wurden nach denselben Bauplänen gebaut. Zehn Häuser (Objekte), ein Satz Blaupausen (Klassendefinition).

instanceofist ein nützliches Werkzeug, wenn Sie eine Sammlung von Objekten haben und nicht sicher sind, was sie sind. Angenommen, Sie haben eine Sammlung von Steuerelementen in einem Formular. Sie möchten den aktivierten Status aller vorhandenen Kontrollkästchen lesen, können jedoch kein einfaches altes Objekt nach dem aktivierten Status fragen. Stattdessen würden Sie sehen, ob jedes Objekt ein Kontrollkästchen ist, und wenn ja, wandeln Sie es in ein Kontrollkästchen um und überprüfen Sie seine Eigenschaften.

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

15
Das heißt, die Verwendung instanceofkann das Downcasting sicher machen.
Raedwald

29

Wie auf dieser Seite beschrieben :

Mit dem instanceofOperator kann getestet werden, ob ein Objekt von einem bestimmten Typ ist ...

if (objectReference instanceof type)

Ein kurzes Beispiel:

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

Das Anwenden instanceofauf eine Nullreferenzvariable / einen Nullreferenzausdruck gibt jedoch false zurück.

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

Da eine Unterklasse ein 'Typ' ihrer Oberklasse ist, können Sie instanceofdies mit ...

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

Ich hoffe das hilft!


15

Mit diesem Operator können Sie den Typ eines Objekts bestimmen. Es gibt einen booleanWert zurück.

Beispielsweise

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

Die Ausgabe ist:

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

14

Wenn sourcees sich um eine objectVariable handelt, instanceofkönnen Sie überprüfen, ob es sich um eine Variable handelt Buttonoder nicht.


4

Wie in anderen Antworten erwähnt, besteht die kanonische typische Verwendung von instanceofdarin, zu überprüfen, ob sich ein Bezeichner auf einen spezifischeren Typ bezieht. Beispiel:

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
}

Beachten Sie jedoch, dass der Typ des linken Ausdrucks ein übergeordneter Typ des rechten Ausdrucks sein muss (siehe JLS 15.20.2 und Java Puzzlers, Nr. 50, S. 114 ). Folgendes kann beispielsweise nicht kompiliert werden:

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

Dies kann nicht mit der Nachricht kompiliert werden:

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

Da Testist keine Elternklasse von String. OTOH, dies kompiliert perfekt und druckt falsewie erwartet:

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

Vielen Dank für den Link zur Spezifikation!
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

Kann als Abkürzung für die Gleichstellungsprüfung verwendet werden.

Also dieser Code

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

Kann geschrieben werden als

if(ob instanceOf ClassA) {
}

1

Die meisten Leute haben das "Was" dieser Frage richtig erklärt, aber niemand hat "Wie" richtig erklärt.

Hier ist eine einfache Illustration:

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

Ausgänge:

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

Der Grund für den Compilerfehler beim Vergleich smit StringBuffer wird in den Dokumenten ausführlich erläutert :

Sie können damit testen, ob ein Objekt eine Instanz einer Klasse, eine Instanz einer Unterklasse oder eine Instanz einer Klasse ist, die eine bestimmte Schnittstelle implementiert.

Dies impliziert, dass die LHS entweder eine Instanz von RHS oder einer Klasse sein muss, die entweder RHS implementiert oder RHS erweitert.

Wie verwende ich dann instanceof?
Da jede Klasse Object erweitert, funktioniert die Typumwandlung von LHS zu Objekt immer zu Ihren Gunsten:

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

Ausgänge:

Not an instance of StringBuffer

Warum wird im letzten Beispiel "Keine Instanz von StringBuffer" zurückgegeben? Da Sie s in Object auf LHS typisiert und überprüft haben, ob es sich um eine Instanz von RHS handelt if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //shouldn't this be true, seit wir s in Object typisiert haben?
sofs1

Da s eine Referenz auf ein String-Objekt ist (Java verwendet im Gegensatz zu C ++ einen dynamischen Polymorphismus) und String keine Unterklasse von StringBuffer ist.
Sziraqui


0

Die Instanz des Schlüsselworts ist hilfreich, wenn Sie die Instanz eines bestimmten Objekts kennen möchten.

Angenommen, Sie sind eine Wurfausnahme. Wenn Sie einen Fang haben, führen Sie eine benutzerdefinierte Summenoperation aus und fahren Sie dann erneut gemäß Ihrer Logik fort (Würfe oder Protokoll usw.).

Beispiel: 1) Der Benutzer hat eine benutzerdefinierte Ausnahme "InvalidExtensionsException" erstellt und diese gemäß der Logik ausgelöst

2) Jetzt im catch-Block catch (Ausnahme e) {Summenlogik ausführen, wenn der Ausnahmetyp "InvalidExtensionsException" ist.

InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;

3) Wenn Sie die Instanz nicht überprüfen und der Ausnahmetyp eine Nullzeigerausnahme ist, wird Ihr Code unterbrochen.

Ihre Logik sollte sich also innerhalb der Instanz von if befinden (e Instanz von InvalidExtensionsException) {InvalidExtensionsException InvalidException = (InvalidExtensionsException) e; }}

Das obige Beispiel ist eine falsche Codierungspraxis. Dieses Beispiel hilft Ihnen jedoch, die Verwendung der Instanz davon zu verstehen.


0

Beste Erklärung ist jls . Versuchen Sie immer zu überprüfen, was die Quelle sagt. Dort erhalten Sie die beste Antwort und vieles mehr. Einige Teile hier reproduzieren:

Der Typ des RelationalExpression-Operanden der Instanz des Operators muss ein Referenztyp oder der Nulltyp sein. Andernfalls tritt ein Fehler bei der Kompilierung auf.

Es handelt sich um einen Fehler bei der Kompilierung, wenn der nach dem Operator instanceof erwähnte ReferenceType keinen referenzierbaren Referenztyp angibt (§4.7).

Wenn eine Umwandlung (§15.16) des RelationalExpression in den ReferenceType als Fehler zur Kompilierungszeit zurückgewiesen wird, erzeugt die Instanz des relationalen Ausdrucks ebenfalls einen Fehler zur Kompilierungszeit. In einer solchen Situation könnte das Ergebnis der Instanz des Ausdrucks niemals wahr sein.


0

Mit dem Java- instanceofOperator wird getestet, ob das Objekt eine Instanz des angegebenen Typs ist (Klasse oder Unterklasse oder Schnittstelle).

Die Instanz von in Java wird auch als Typ bezeichnet, comparison operatorda sie die Instanz mit dem Typ vergleicht. Es gibt entweder trueoder zurück false. Wenn wir den instanceofOperator mit einer Variablen anwenden, die einen nullWert hat, wird er zurückgegeben false.

Ab JDK 14+, das JEP 305 enthält , können wir auch "Pattern Matching" für durchführeninstanceof

Muster testen grundsätzlich, ob ein Wert einen bestimmten Typ hat, und können Informationen aus dem Wert extrahieren, wenn er den passenden Typ hat. Der Mustervergleich ermöglicht einen klareren und effizienteren Ausdruck der allgemeinen Logik in einem System, nämlich das bedingte Entfernen von Komponenten aus Objekten.

Vor Java 14

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

Java 14-Verbesserungen

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

Wir können auch die Typprüfung und andere Bedingungen miteinander kombinieren

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

Die Verwendung von Pattern Matching in instanceofsollte die Gesamtzahl der expliziten Casts in Java-Programmen reduzieren.

PS : instanceOfstimmt nur überein, wenn das Objekt nicht null ist, dann kann nur es zugewiesen werden 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
Veröffentlichen Sie nicht nur Antworten auf StackOverflow. Bitte fügen Sie eine Erklärung hinzu.
L. Guthardt

-2

Sehr einfaches Codebeispiel:

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

Sei hier vorsichtig. Wenn im obigen Beispiel Klasse1 Objekt ist, ist der erste Vergleich immer wahr. Also, genau wie mit Ausnahmen, ist die hierarchische Reihenfolge wichtig!


-2

Sie können Map verwenden, um eine höhere Abstraktion für eine Instanz von zu erstellen

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

Wenn Sie dann eine solche Karte haben, fügen Sie ihr eine Aktion hinzu:

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

Wenn Sie dann ein Objekt vom unbekannten Typ haben, können Sie eine bestimmte Aktion von dieser Karte erhalten:

actions.get(someObject).accept(someObject)

-2

Mit dem Operator instanceof wird überprüft, ob das Objekt eine Instanz des angegebenen Typs ist. (Klasse oder Unterklasse oder Schnittstelle).

Die Instanz von wird auch als Typvergleichsoperator bezeichnet, da sie die Instanz mit dem Typ vergleicht. Es wird entweder wahr oder falsch zurückgegeben.

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

Wenn wir den Operator instanceof auf eine Variable mit dem Wert null anwenden, wird false zurückgegeben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.