A cosa serve l'operatore 'instanceof' in Java?


163

A cosa serve l' instanceofoperatore? Ho visto cose del genere

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

Ma niente di tutto ciò aveva senso per me. Ho fatto le mie ricerche, ma ho trovato solo esempi senza spiegazioni.


38
Non c'è nulla di sbagliato nel porre domande qui, ma se stai imparando Java potresti voler ottenere un libro. Qualsiasi libro Java decente avrebbe la risposta a questa domanda e ai prossimi 1000 che avrai.
Presidente James K. Polk,

Tale operatore ha molti usi specifici. Questa sarebbe una domanda specifica se chiedesse una spiegazione di uno degli esempi che non aveva senso per te.
Raedwald,

2
Le risposte di seguito sono corrette, tuttavia si noti che instanceof è un operatore abusato 9 volte su 10, può essere sostituito da un uso corretto del polimorfismo (non sempre, ma spesso)
Richard Tingle,

Andrei oltre quello di Richard: non ho MAI visto un uso valido di instanceof. È utile solo per trucchi rapidi in aggiunta a codice mal progettato. Se non ti piace OOP, scrivi in ​​un'altra lingua (ce ne sono molte). Di '"no" a instanceof!
Scott Biggs,

5
@ScottBiggs C'è una buona alternativa a instanceofquando si esegue l' override equals?
Ben Aaronson,

Risposte:


228

instanceofparola chiave è un operatore binario utilizzato per verificare se un oggetto (istanza) è un sottotipo di un determinato Tipo.

Immaginare:

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

Immagina un dog oggetto , creato con Object dog = new Dog(), quindi:

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

Tuttavia, con Object animal = new Animal();,

animal instanceof Dog // false

perché Animalè un supertipo Doge forse meno "raffinato".

E,

dog instanceof Cat // does not even compile!

Questo perché Dognon è né un sottotipo né un supertipo di Cat, e inoltre non lo implementa.

Si noti che la variabile utilizzata per dogsopra è di tipo Object. Questo per mostrare instanceofè un'operazione di runtime e ci porta a un / il caso d'uso: reagire in modo diverso sulla base di un tipo di oggetti in fase di runtime .

Cose da notare: expressionThatIsNull instanceof Tè falso per tutti i tipi T.

Buona codifica.


14
Ho appena provato - Object dog = new Dog(); System.out.println(dog instanceof Cat);. Questo compila bene e stampa false. Al compilatore non è consentito determinare in fase di compilazione che dognon può essere un gatto (secondo le regole del JLS)
Erwin Bolwidt,

@ErwinBolwidt Hai fatto un errore quando l'hai provato. Per chiunque si chieda: JLS Sezione 15.20.2 è quella che stai cercando. Per un esempio minimo di non lavoro:boolean b = "foo" instanceof Integer;
Felix S

3
@FelixS Devi leggere di nuovo la risposta. La risposta è di circa Object indirect = ...; if (indirect instanceof Something). Non si tratta di if (literal instanceof Something)come sembra che tu stia assumendo.
Erwin Bolwidt,

1
@ErwinBolwidt Oh, giusto, devo aver saltato la Object dogparte. Colpa mia!
Felix S

dog instanceof Cat // does not even compile!(perché è una classe). Se Catfosse un'interfaccia allora si compilerebbe.
Hamza Belmellouki,

44

È un operatore che restituisce true se il lato sinistro dell'espressione è un'istanza del nome della classe sul lato destro.

Pensaci in questo modo. Supponiamo che tutte le case del tuo blocco siano state costruite con gli stessi progetti. Dieci case (oggetti), una serie di progetti (definizione di classe).

instanceofè uno strumento utile quando hai una collezione di oggetti e non sei sicuro di cosa siano. Supponiamo che tu abbia una raccolta di controlli in un modulo. Vuoi leggere lo stato controllato di qualunque casella di controllo ci sia, ma non puoi chiedere a un vecchio oggetto semplice il suo stato controllato. Invece, vedresti se ogni oggetto è una casella di controllo e, se lo è, esegui il cast in una casella di controllo e controlla le sue proprietà.

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

15
Vale a dire, l'uso instanceofpuò rendere sicuro il downcast.
Raedwald,

29

Come descritto in questo sito :

L' instanceofoperatore può essere utilizzato per verificare se un oggetto è di un tipo specifico ...

if (objectReference instanceof type)

Un rapido esempio:

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

Tuttavia, l'applicazione instanceofsu una variabile / espressione di riferimento null restituisce false.

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

Poiché una sottoclasse è un 'tipo' della sua superclasse, è possibile utilizzare il instanceofper verificare questo ...

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

Spero che aiuti!


15

Questo operatore consente di determinare il tipo di un oggetto. Restituisce aboolean valore.

Per esempio

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

l'output è:

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

14

If sourceè una objectvariabile, instanceofè un modo per verificare se è Buttono meno.


5

Come menzionato in altre risposte, l'uso tipico canonico di instanceofè per verificare se un identificatore si riferisce a un tipo più specifico. Esempio:

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
}

Si noti tuttavia che il tipo dell'espressione per la mano sinistra deve essere un tipo genitore dell'espressione per la mano destra (vedere JLS 15.20.2 e Java Puzzlers, # 50, pp114 ). Ad esempio, non sarà possibile compilare quanto segue:

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

Questo non riesce a compilare con il messaggio:

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

Come Testnon è una classe genitore di String. OTOH, questo si compila perfettamente e stampa falsecome previsto:

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

Grazie per il collegamento alle specifiche!
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

Può essere usato come scorciatoia nel controllo dell'uguaglianza.

Quindi questo codice

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

Può essere scritto come

if(ob instanceOf ClassA) {
}

1

Molte persone hanno spiegato correttamente il "Cosa" di questa domanda, ma nessuno ha spiegato correttamente "Come".

Quindi ecco una semplice illustrazione:

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

Uscite:

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

Il motivo dell'errore del compilatore durante il confronto scon StringBuffer è ben spiegato nei documenti :

Puoi usarlo per verificare se un oggetto è un'istanza di una classe, un'istanza di una sottoclasse o un'istanza di una classe che implementa una particolare interfaccia.

il che implica che LHS deve essere un'istanza di RHS o di una classe che implementa RHS o estende RHS.

Come usare use instanceof allora?
Poiché ogni classe estende Object, la fusione di tipi LHS all'oggetto funzionerà sempre a tuo favore:

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

Uscite:

Not an instance of StringBuffer

Nell'ultimo esempio, perché viene restituito "Not a instance of StringBuffer"? Dato che hai scritto a macchina su Object su LHS e hai verificato se si tratta di un'istanza di RHS if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //shouldn't this be true, dal momento che stiamo scrivendo a macchina su Object?
sofs1,

Poiché s è un riferimento all'oggetto String (Java utilizza un polimorfismo dinamico a differenza del C ++) e String non è una sottoclasse di StringBuffer.
sziraqui,


0

L'istanza della parola chiave è utile quando si desidera conoscere l'istanza di un oggetto particolare.

Supponiamo che tu abbia generato un'eccezione e quando hai catturato esegui quindi un'operazione di somma personalizzata e poi continua di nuovo secondo la tua logica (lancia o registra ecc.)

Esempio: 1) L'utente ha creato l'eccezione personalizzata "InvalidExtensionsException" e la lancia come da logica

2) Ora in catch block catch (Exception e) {esegue la logica di somma se il tipo di eccezione è "InvalidExtensionsException"

InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;

3) Se non si controlla l'istanza di e il tipo di eccezione è l'eccezione Puntatore null, il codice verrà interrotto.

Quindi la tua logica dovrebbe essere all'interno dell'istanza di if (e instanceof InvalidExtensionsException) {InvalidExtensionsException InvalidException = (InvalidExtensionsException) e; }

L'esempio sopra è una pratica di codifica errata Tuttavia questo esempio ti aiuta a capire l'uso dell'istanza di esso.


0

La migliore spiegazione è jls . Cerca sempre di controllare cosa dice la fonte. Lì otterrai la risposta migliore e molto altro ancora. Riproduzione di alcune parti qui:

Il tipo dell'operando RelationalExpression dell'operatore instanceof deve essere un tipo di riferimento o un tipo null; in caso contrario, si verifica un errore in fase di compilazione.

È un errore in fase di compilazione se il Tipo di riferimento menzionato dopo l'operatore dell'istanza non indica un tipo di riferimento riutilizzabile (§4.7).

Se un cast (§15.16) di RelationalExpression a ReferenceType verrebbe rifiutato come errore in fase di compilazione, allora anche l'istanza dell'espressione relazionale produce un errore in fase di compilazione. In una situazione del genere, il risultato dell'espressione dell'istanza non potrebbe mai essere vero.


0

L' instanceofoperatore java viene utilizzato per verificare se l'oggetto è un'istanza del tipo specificato (classe o sottoclasse o interfaccia).

L'istanza di java è anche nota come tipo comparison operatorin quanto confronta l'istanza con il tipo. Restituisce trueo false. Se applichiamo l' instanceofoperatore con qualsiasi variabile che abbia nullvalore, restituiscefalse .

Da JDK 14+ che include JEP 305 possiamo anche fare "Pattern Matching" perinstanceof

I pattern testano fondamentalmente che un valore ha un certo tipo e possono estrarre informazioni dal valore quando ha il tipo corrispondente. La corrispondenza dei modelli consente un'espressione più chiara ed efficiente della logica comune in un sistema, vale a dire la rimozione condizionale dei componenti dagli oggetti.

Prima di Java 14

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

Miglioramenti di Java 14

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

Possiamo anche combinare il controllo del tipo e altre condizioni insieme

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

L'uso del pattern matching in instanceofdovrebbe ridurre il numero complessivo di cast espliciti nei programmi Java.

PS : instanceOfcorrisponderà solo quando l'oggetto non è null, quindi solo a lui può essere assegnato 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
Non pubblicare risposte di codice solo su StackOverflow. Vai avanti e aggiungi una spiegazione.
L. Guthardt,

-2

Esempio di codice molto semplice:

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

Stai attento qui. Nell'esempio sopra, se Class1 è Object, il primo confronto sarà sempre vero. Quindi, proprio come con le eccezioni, l'ordine gerarchico conta!


-2

È possibile utilizzare la mappa per aumentare l'astrazione su istanza di

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

Quindi facendo in modo che tale mappa aggiunga qualche azione ad essa:

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

Quindi avendo un oggetto di tipo non noto potresti ottenere un'azione specifica da quella mappa:

actions.get(someObject).accept(someObject)

-2

L'operatore instanceof viene utilizzato per verificare se l'oggetto è un'istanza del tipo specificato. (classe o sottoclasse o interfaccia).

L'istanza è anche conosciuta come operatore di confronto dei tipi perché confronta l'istanza con il tipo. Restituisce vero o falso.

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

Se applichiamo l'operatore instanceof con qualsiasi variabile che ha valore null, restituisce false.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.