JavaRush /Blog Java /Random-PL /Operator instancjiof w Javie

Operator instancjiof w Javie

Opublikowano w grupie Random-PL
Cześć! Dzisiaj porozmawiamy o operatorze instancjiof, przyjrzymy się przykładom jego użycia i poruszymy pewne kwestie związane z jego działaniem :) Na wczesnych poziomach JavaRush spotkałeś się już z tym operatorem. Czy pamiętasz, dlaczego jest to potrzebne? Jeśli nie, to nie ma znaczenia, pamiętajmy razem. Operator instancjiof jest potrzebny do sprawdzenia, czy obiekt, do którego odwołuje się zmienna X, został utworzony z jakiejś klasy Y. Brzmi prosto. Dlaczego wróciliśmy do tego tematu? Po pierwsze dlatego, że teraz dobrze znasz mechanizm dziedziczenia w Javie i inne zasady OOP. Temat instancjiof będzie znacznie jaśniejszy i przyjrzymy się bardziej zaawansowanym przypadkom użycia. Iść! Jak działa operator Instanceof - 1Prawdopodobnie pamiętasz, że operator instancjiof zwraca wartość true , jeśli test był prawdziwy, lub false , jeśli wynik był fałszywy. W związku z tym najczęściej spotyka się go w różnego rodzaju warunkach testowych ( if…else). Zacznijmy od 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ślisz, co zostanie wyprowadzone na konsolę? Cóż, tutaj jest to oczywiste :) Obiekt хjest liczbą całkowitą, więc wynik będzie prawdziwy . Wyjście konsoli: true Spróbujmy sprawdzić, czy należy on np. do String:
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String);// błąd!
   }
}
Otrzymaliśmy błąd. I zwróć uwagę: kompilator wydał to jeszcze przed wykonaniem kodu! Od razu zauważył, że Integer i String nie mogą być automatycznie konwertowane na siebie i nie mają relacji dziedziczenia. Dlatego obiekt klasy Integer nie zostanie utworzony na podstawie String. Jest to wygodne i pozwala uniknąć dziwnych błędów już podczas wykonywania programu, więc kompilator nam w tym pomógł :) Spróbujmy teraz przyjrzeć się bardziej złożonym przykładom. Skoro wspomnieliśmy o dziedziczeniu, popracujmy z tym systemem małych klas:
public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}
Wiemy już, jak zachowuje się instancja, gdy w normalnej sytuacji sprawdzamy, czy obiekt należy do klasy, ale co się stanie, jeśli dodamy tutaj relację rodzic-dziecko? Jak działa operator Instanceof - 2 Na przykład, jak myślisz, co przyniesie poniższa kontrola:
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);

   }
}
Wynik: prawda fałsz Główne pytanie, na które należy odpowiedzieć, brzmi: w jaki sposób instancja odszyfrowuje koncepcję „obiektu utworzonego na podstawie klasy”? W rezultacie dostaliśmy to Сat instanceof Animal == true, ale przy takim sformułowaniu można znaleźć pewne wady. Dlaczego ten obiekt jest Cattworzony w oparciu o klasę Animal? Czy nie jest on stworzony wyłącznie w oparciu o własną klasę? Odpowiedź jest dość prosta i być może już ją odkryłeś. Podczas tworzenia obiektu pamiętaj o kolejności wywoływania konstruktorów i inicjowania zmiennych. Temat ten poruszaliśmy już w artykule o konstruktorze klas . Oto przykład z tego wykładu:
public class Animal {

   String brain = „Początkowa wartość mózgu w klasie zwierząt”;
   String heart = „Początkowa wartość serca w klasie zwierząt”;

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println(„Trwa wykonywanie konstruktora klasy bazowej Animal”);
       System.out.println(„Czy zmienne klasy Animal zostały już zainicjowane?”);
       System.out.println(„Bieżąca wartość zmiennej statycznej animalCount =” + animalCount);
       System.out.println(„Aktualna wartość mózgu w klasie Animal =” + this.brain);
       System.out.println(„Aktualna wartość serca w klasie Animal =” + this.heart);

       this.brain = brain;
       this.heart = heart;
       System.out.println(„Konstruktor podstawowej klasy zwierząt został ukończony!”);
       System.out.println(„Aktualna wartość mózgu =” + this.brain);
       System.out.println(„Aktualna wartość serca =” + this.heart);
   }
}

class Cat extends Animal {

   String tail = „Początkowa wartość ogona w klasie Cat”;

   static int catsCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println(„Konstruktor klasy Cat został uruchomiony (konstruktor Animal został już wykonany)”);
       System.out.println(„Bieżąca wartość zmiennej statycznej kotyCount =” + catsCount);
       System.out.println(„Ogon wartości bieżącej =” + this.tail);
       this.tail = tail;
       System.out.println(„Ogon wartości bieżącej =” + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Mózg", "Serce", "Ogon");
   }
}
A jeśli uruchomisz go w IDE, wynik konsoli będzie wyglądał następująco: Konstruktor klasy bazowej Animal jest uruchomiony. Czy zmienne klasy Animal zostały już zainicjowane? Aktualna wartość zmiennej statycznej AnimalCount = 7700000 Aktualna wartość mózgu w klasie Animal = Początkowa wartość mózgu w klasie Animal Aktualna wartość serca w klasie Animal = Początkowa wartość serca w klasie Animal Konstruktor bazowej klasy Animal zakończył swoje dzieło! Aktualna wartość mózgu = Brain Aktualna wartość serca = Serce Konstruktor klasy Cat rozpoczął pracę (konstruktor Animal został już wykonany) Aktualna wartość zmiennej statycznej catCount = 37 Aktualna wartość ogona = Początkowa wartość ogona w Klasa kota Aktualna wartość ogona = Ogon Czy pamiętasz teraz? :) Konstruktor klasy bazowej, jeśli taki istnieje, jest zawsze wywoływany jako pierwszy podczas tworzenia dowolnego obiektu. Instanceof postępuje zgodnie z tą zasadą, próbując ustalić, czy obiekt został Аutworzony na podstawie klasy Б. Jeśli wywołany zostanie konstruktor klasy bazowej, nie może być wątpliwości. Dzięki drugiemu sprawdzeniu wszystko jest prostsze:
System.out.println(cat instanceof MaineCoon);
Konstruktor MaineCoonnie został wywołany podczas tworzenia Cat, co jest logiczne. W końcu MaineCoonjest potomkiem Cat, a nie przodkiem. Ale Catto nie jest szablon. OK, to wydaje się jasne. 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);


   }
}
Hmm... to jest bardziej skomplikowane. Spróbujmy uzasadnić. Mamy zmienną typu Cati przypisaliśmy do niej obiekt typu MaineCoon. Swoją drogą, dlaczego to w ogóle działa? Czy jest to możliwe? Móc. W końcu każdy Maine Coon jest kotem. Jeśli nie jest to do końca jasne, pamiętaj przykład z rozszerzeniami typu pierwotnego:
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 , bo wystarczy jej ilość bajtów (pamiętasz przykład z lalkami gniazdującymi?). Obiekt podrzędny można zawsze przypisać do zmiennej nadrzędnej. Po prostu zapamiętaj to na razie, a w kolejnych wykładach będziemy dokładniej analizować ten proces. Co zatem przyniesie nasz przykład?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
Co instancja sprawdzi: zmienną naszej klasy Catczy obiekt naszej klasy MaineCoon? Właściwie odpowiedź na to pytanie jest prosta. Wystarczy jeszcze raz przeczytać definicję naszego operatora: Operator instancjiof jest potrzebny do sprawdzenia, czy obiekt, do którego odwołuje się zmienna, został Xutworzony w oparciu o jakąś klasę Y. Operator instancjiof sprawdza pochodzenie obiektu, a nie zmiennej. Dlatego w tym przykładzie za każdym razem w konsoli wyświetli się wartość true : mamy obiekt typu MaineCoon. Oczywiście został stworzony w oparciu o klasę MaineCoon, ale także w oparciu o klasę nadrzędną Cat!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION