Ciao! Oggi parleremo dell'istanza dell'operatore, vedremo esempi del suo utilizzo e toccheremo alcuni punti relativi al suo funzionamento :) Ai primi livelli di JavaRush, hai già incontrato questo operatore. Ricordi perché è necessario? Altrimenti non importa, ricordiamolo insieme. L'operatore istanza di è necessario per verificare se l'oggetto a cui fa riferimento la variabile X è stato creato da una classe Y. Sembra semplice. Perché siamo tornati su questo argomento? Innanzitutto perché ora conosci bene il meccanismo di ereditarietà in Java e altri principi OOP. L'argomento di exampleof sarà molto più chiaro e esamineremo casi d'uso più avanzati. Andare! Probabilmente ricorderete che l'operatore istanzadi restituisce vero se il test era vero, o falso se il risultato era falso. Di conseguenza, si trova più spesso in vari tipi di condizioni di test (
if…else
). Cominciamo con esempi più semplici:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
Cosa pensi che verrà visualizzato sulla console? Bene, qui è ovvio :) L'oggetto х
è un numero intero, quindi il risultato sarà true . Output della console: true Proviamo a verificare se appartiene, ad esempio, a String:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
Abbiamo ricevuto un errore. E attenzione: il compilatore lo ha rilasciato ancor prima che il codice fosse eseguito! Ha subito visto che Integer e String non possono essere convertiti automaticamente l'uno nell'altro e non hanno relazioni di ereditarietà. Pertanto, un oggetto di classe Integer non verrà creato dalla String. Questo è comodo e aiuta a evitare strani errori già durante l'esecuzione del programma, quindi il compilatore ci ha aiutato qui :) Ora proviamo a guardare esempi più complessi. Dato che abbiamo menzionato l'ereditarietà, lavoriamo con questo sistema di piccole classi:
public class Animal {
}
public class Cat extends Animal {
}
public class MaineCoon extends Cat {
}
Sappiamo già come si comporta exampleof quando controlliamo se un oggetto appartiene a una classe in una situazione normale, ma cosa succede se aggiungiamo qui una relazione genitore-figlio? Ad esempio, cosa pensi che produrrà il seguente controllo:
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat instanceof Animal);
System.out.println(cat instanceof MaineCoon);
}
}
Risultato: true false La domanda principale a cui è necessario rispondere è: come fa esattamente exampleof a decifrare il concetto di "un oggetto creato sulla base di una classe"? Di conseguenza, l'abbiamo ottenuto Сat instanceof Animal == true
, ma si può trovare da ridire su una simile formulazione. Perché questo oggetto viene Cat
creato in base alla classe Animal
? Non è stato creato solo in base alla propria classe? La risposta è abbastanza semplice e potresti averlo già capito. Ricordare l'ordine in cui vengono chiamati i costruttori e le variabili vengono inizializzate durante la creazione di un oggetto. Abbiamo già trattato questo argomento nell'articolo sul costruttore della classe . Ecco un esempio da quella conferenza:
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
E se lo esegui nell'IDE, l'output della console sarà simile a questo: Il costruttore della classe base Animal è in esecuzione. Le variabili della classe Animal sono già state inizializzate? Valore corrente della variabile statica AnimalCount = 7700000 Valore corrente del cervello nella classe Animale = Valore iniziale del cervello nella classe Animale Valore corrente del cuore nella classe Animale = Valore iniziale del cuore nella classe Animale Il costruttore della classe base Animale ha completato il suo lavoro! Valore attuale di brain = Brain Valore attuale di heart = Heart Il costruttore della classe Cat ha iniziato a funzionare (il costruttore Animal è già stato eseguito) Valore attuale della variabile statica catsCount = 37 Valore attuale di tail = Valore iniziale di tail nel Classe gatto Valore attuale della coda = Coda Ti ricordi adesso? :) Il costruttore della classe base, se ce n'è uno, viene sempre chiamato per primo quando si crea qualsiasi oggetto. Instanceof segue questo principio quando tenta di determinare se un oggetto è stato А
creato da una classe Б
. Se viene chiamato il costruttore della classe base, non ci possono essere dubbi. Con il secondo controllo tutto è più semplice:
System.out.println(cat instanceof MaineCoon);
Il costruttore MaineCoon
non è stato chiamato durante la creazione Cat
, il che è logico. Dopotutto, MaineCoon
è un discendente Cat
, non un antenato. Ma Cat
non è un modello per. Ok, questo sembra chiaro. Cosa accadrà se lo facciamo:
public class Main {
public static void main(String[] args) {
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
}
}
Hmm... questo è più complicato. Proviamo a ragionare. Abbiamo una variabile di tipo Cat
e le abbiamo assegnato un oggetto di tipo MaineCoon
. A proposito, perché funziona? È possibile farlo? Potere. Dopotutto, ogni Maine Coon è un gatto. Se non è del tutto chiaro, ricorda l'esempio con estensioni di tipo primitivo:
public class Main {
public static void main(String[] args) {
long x = 1024;
}
}
Il numero 1024 è corto : si adatta facilmente alla variabile long , perché il numero di byte è sufficiente (ricordate l'esempio con le bambole che nidificano?). Un oggetto figlio può sempre essere assegnato a una variabile antenato. Per ora ricordatelo e nelle prossime lezioni analizzeremo ulteriormente questo processo. Quindi cosa produrrà il nostro esempio?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
Cosa controllerà l'istanza di: la nostra variabile di classe Cat
o il nostro oggetto di classe MaineCoon
? In realtà, la risposta a questa domanda è semplice. Devi solo leggere di nuovo la definizione del nostro operatore: L'operatore istanzaof è necessario per verificare se l'oggetto a cui fa riferimento la variabile è stato X
creato in base a qualche classe Y
. L'operatore "instanceof" controlla l'origine di un oggetto, non di una variabile. Pertanto, nell'esempio, entrambe le volte verrà visualizzato true nella console : abbiamo un oggetto di tipo MaineCoon
. Naturalmente è stato creato in base alla classe MaineCoon
, ma anche in base alla classe genitore Cat
!
GO TO FULL VERSION