CodeGym /Blog Java /Random-PL /Instancja Java operatora
Autor
Jesse Haniel
Lead Software Architect at Tribunal de Justiça da Paraíba

Instancja Java operatora

Opublikowano w grupie Random-PL
Cześć! Dzisiaj porozmawiamy o operatorze instanceof , rozważymy przykłady jego użycia i dotkniemy niektórych aspektów jego działania :) Spotkałeś się już z tym operatorem na wczesnych poziomach CodeGym. Czy pamiętasz, dlaczego go potrzebujemy? Jeśli nie, nie martw się. Pamietajmy razem. Operator instanceof jest potrzebny do sprawdzenia, czy obiekt, do którego odwołuje się zmienna X , został utworzony na podstawie jakiejś klasy Y. To brzmi prosto. Dlaczego wróciliśmy do tego tematu? Przede wszystkim dlatego, że jesteś już dobrze zaznajomiony z mechanizmem dziedziczenia w Javie i innymi zasadami OOP. Operator instanceof będzie teraz znacznie bardziej przejrzysty i przyjrzymy się bardziej zaawansowanym przykładom jego użycia. Chodźmy!Jak działa operator instanceof — 1Prawdopodobnie pamiętasz, że operator instanceof zwraca wartość true , jeśli sprawdzenie ma wartość true, lub false , jeśli wyrażenie jest fałszywe. W związku z tym zwykle występuje we wszelkiego rodzaju wyrażeniach warunkowych ( if…else ). Zacznijmy od kilku prostszych przykładów:

public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof Integer);
   }
}
Jak myślicie, co będzie wyświetlane na konsoli? Cóż, tutaj jest to oczywiste.:) Obiekt x jest liczbą całkowitą, więc wynikiem będzie prawda . Dane wyjściowe konsoli: True Spróbujmy sprawdzić, czy jest to String :

public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String); // Error!
   }
}
Wystąpił błąd. I zwróć uwagę: kompilator wygenerował błąd przed uruchomieniem kodu! Od razu zauważył, że Integer i String nie mogą być automatycznie konwertowane na siebie i nie są powiązane przez dziedziczenie. W związku z tym obiekt Integer nie jest tworzony na podstawie String . Jest to wygodne i pomaga uniknąć dziwnych błędów w czasie wykonywania, więc kompilator nam w tym pomógł :) Spróbujmy teraz rozważyć przykłady, które są trudniejsze. Ponieważ wspomnieliśmy o dziedziczeniu, popracujmy z następującym małym systemem klas:

public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}
Wiemy już, jak zachowuje się instanceof , gdy sprawdzamy, czy obiekt jest instancją klasy, ale co się stanie, jeśli weźmiemy pod uwagę relację rodzic-dziecko? Na przykład, jak myślisz, co dadzą te wyrażenia:

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

   }
}
Dane wyjściowe: Prawda Fałsz Głównym pytaniem, na które należy odpowiedzieć, jest dokładnie to, w jaki sposób instanceof interpretuje „obiekt utworzony na podstawie klasy”? „ cat instanceof Animal ” ma wartość true , ale z pewnością możemy znaleźć błąd w tym sformułowaniu. Dlaczego obiekt Cat jest tworzony na podstawie klasy Animal ? Czy nie jest tworzony wyłącznie w oparciu o własną klasę? Odpowiedź jest dość prosta i być może już o tym pomyślałeś. Pamiętaj o kolejności wywoływania konstruktorów i inicjalizacji zmiennych podczas tworzenia obiektu. Omówiliśmy już ten temat w artykule o konstruktorach klas . Oto przykład z tej lekcji:

public class Animal {

   String brain = "Initial value of brain in the Animal class";
   String heart = "Initial value of heart in the Animal class";

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println("Animal base class constructor is running");
       System.out.println("Have the variables of the Animal class already been initialized?");
       System.out.println("Current value of static variable animalCount = " + animalCount);
       System.out.println("Current value of brain in the Animal class = " + this.brain);
       System.out.println("Current value of heart in the Animal class = " + this.heart);
       System.out.println("Have the variables of the Cat class already been initialized?");
       System.out.println("Current value of static variable catCount = " + Cat.catCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor is done!");
       System.out.println("Current value of brain = " + this.brain);
       System.out.println("Current value of heart = " + this.heart);
   }
}

public class Cat extends Animal {

   String tail = "Initial value of tail in the Cat class";

   static int catCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println("The Cat class constructor has started (The Animal constructor already finished)");
       System.out.println("Current value of static variable catCount = " + catCount);
       System.out.println("Current value of tail = " + this.tail);
       this.tail = tail;
       System.out.println("Current value of tail = " + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
A jeśli uruchomisz go w środowisku IDE, dane wyjściowe konsoli będą wyglądać następująco: Konstruktor klasy bazowej Animal jest uruchomiony Czy zmienne klasy Animal zostały już zainicjowane? Bieżąca wartość zmiennej statycznej animalCount = 7700000 Bieżąca wartość mózgu w klasie Animal = Początkowa wartość mózgu w klasie Animal Bieżąca wartość serca w klasie Animal = Początkowa wartość serca w klasie Animal Czy zmienne klasy Kot są już został zainicjowany? Bieżąca wartość zmiennej statycznej catCount = 37 Konstruktor klasy bazowej Animal jest gotowy! Aktualna wartość brain = Brain Aktualna wartość heart = Heart Konstruktor klasy cat został uruchomiony (Konstruktor Animal został już zakończony) Aktualna wartość zmiennej statycznej catCount = 37 Aktualna wartość tail = Początkowa wartość tail w klasie Cat Aktualna wartość tail = Ogon Pamiętasz teraz?:) Konstruktor klasy bazowej, jeśli klasa bazowa istnieje, jest zawsze wywoływany jako pierwszy podczas tworzenia obiektu. Operator instanceof kieruje się tą zasadą przy próbie ustalenia, czy obiekt A został stworzony na podstawie klasy B. Jeśli wywoływany jest konstruktor klasy bazowej, nie ma wątpliwości. Przy drugim sprawdzeniu wszystko jest prostsze:

System.out.println(cat instanceof MaineCoon);
Konstruktor MaineCoon nie został wywołany podczas tworzenia obiektu Cat , co ma sens. W końcu MaineCoon jest potomkiem Kota , a nie przodkiem. I nie jest to szablon dla Cat . Ok, myślę, że mamy jasność. Ale co się stanie, jeśli to zrobimy?:

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


   }
}
Hm... teraz jest trudniej. Porozmawiajmy o tym. Mamy zmienną Cat , do której przypisaliśmy obiekt MaineCoon . Swoją drogą, dlaczego to w ogóle działa? Możemy to zrobić, prawda? Tak możemy. W końcu każdy MaineCoon to kot. Jeśli nie jest to do końca jasne, pamiętaj o przykładzie rozszerzania typów pierwotnych:

public class Main {

   public static void main(String[] args) {

       long x = 1024;

   }
}
Liczba 1024 jest krótka : łatwo mieści się w długiej zmiennej, ponieważ jest wystarczająco dużo bajtów, aby ją pomieścić (pamiętasz przykład z lalkami?). Obiekt potomny zawsze można przypisać do zmiennej przodka. Na razie zapamiętaj to, a na kolejnych lekcjach przeanalizujemy, jak to działa. Co zatem daje nasz przykład?

Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
Co sprawdzi instanceof ? nasza zmienna Cat czy nasz obiekt MaineCoon ? Odpowiedź brzmi: to pytanie jest właściwie proste. Wystarczy jeszcze raz przeczytać definicję operatora: Operator instanceof jest potrzebny do sprawdzenia, czy obiekt, do którego odwołuje się zmienna X , został utworzony na podstawie jakiejś klasy Y. Operator instanceof sprawdza pochodzenie obiektu, a nie typ zmiennej. Zatem w tym przykładzie nasz program wyświetli true w obu przypadkach: mamy obiekt MaineCoon . Oczywiście został stworzony w oparciu o klasę MaineCoon , ale został stworzony w oparciu o Catklasa rodzicielska również!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION