Operator instanceof
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 31 z 87.
Poprzednia lekcja pokazała, że rzutowanie w dół może zakończyć się błędem ClassCastException, jeśli obiekt w rzeczywistości nie jest typu, na który go rzutujesz. Operator instanceof rozwiązuje ten problem, umożliwiając sprawdzenie typu obiektu przed rzutowaniem.
Składnia jest prosta: object instanceof ClassName zwraca true, jeśli obiekt jest instancją tej klasy (lub którejś z jej podklas):
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Można bezpiecznie wywoływać metody specyficzne dla Dog
}To sprawdzenie zapobiega błędom czasu wykonania, upewniając się, że rzutowanie się powiedzie. Operator zwraca również true dla typów nadrzędnych w hierarchii:
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueOd Java 16 możesz połączyć sprawdzenie i rzutowanie w jednym kroku, używając dopasowywania do wzorca:
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' jest już rzutowany i gotowy do użycia
}Ta czytelniejsza składnia eliminuje osobną linię rzutowania. Zauważ, że instanceof zwraca false, gdy jest sprawdzane dla null, więc nie potrzebujesz osobnego sprawdzenia wartości null.
Wyzwanie
ŁatwyZbudujmy system kontroli pojazdów, który używa operatora instanceof do bezpiecznego rozpoznawania i obsługi różnych typów pojazdów. Utworzysz hierarchię pojazdów i napiszesz kod, który sprawdza rzeczywisty typ każdego pojazdu przed uzyskaniem dostępu do jego wyspecjalizowanych funkcji.
Rozmieścisz swój kod w czterech plikach:
Vehicle.java: Utwórz klasę bazową wspólną dla wszystkich pojazdów. Każdy pojazd ma polemodel(String). Dodaj konstruktor, który je inicjalizuje, metodę pobierającą wartośćgetModel()oraz metodęinspect(), która wyświetla:Inspecting vehicle: [model]Car.java: Utwórz klasę rozszerzającą Vehicle. Samochody mają dodatkowe polenumDoors(int). Użyjsuper, aby zainicjalizować klasę nadrzędną. Dodaj metodęcheckDoors(), która wyświetla:[model] has [numDoors] doorsMotorcycle.java: Utwórz kolejną klasę rozszerzającą Vehicle. Motocykle mają polehasSidecar(boolean). Dodaj metodęcheckSidecar(), która wyświetla[model] has a sidecaralbo[model] has no sidecar, w zależności od wartości logicznej.Main.java: To właśnie tutajinstanceofstaje się niezbędny! Otrzymasz cztery dane wejściowe: model samochodu, liczbę drzwi, model motocykla oraz informację, czy ma boczny wózek (true/false).Utwórz tablicę odwołań typu
Vehicle, zawierającą obiekt Car i obiekt Motorcycle. Następnie przejdź pętlą przez tablicę i dla każdego pojazdu:- Wywołaj bazową metodę
inspect() - Użyj
instanceof, aby sprawdzić, czy jest to Car — jeśli tak, bezpiecznie rzutuj typ w dół i wywołajcheckDoors() - Użyj
instanceof, aby sprawdzić, czy jest to Motorcycle — jeśli tak, bezpiecznie rzutuj typ w dół i wywołajcheckSidecar()
- Wywołaj bazową metodę
Otrzymasz cztery dane wejściowe: model samochodu (String), liczbę drzwi (int), model motocykla (String) oraz informację o tym, czy ma boczny wózek (boolean).
Wynik powinien zawierać cztery wiersze — dla każdego pojazdu zobaczysz komunikat o jego kontroli, a po nim sprawdzenie właściwe dla jego typu. Operator instanceof gwarantuje, że metody Car będą wywoływane tylko dla obiektów Car, a metody Motorcycle tylko dla obiektów Motorcycle, zapobiegając wystąpieniu wyjątku ClassCastException!
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Wczytaj dane wejściowe
String carModel = scanner.nextLine();
int numDoors = Integer.parseInt(scanner.nextLine());
String motorcycleModel = scanner.nextLine();
boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
// TODO: Utwórz obiekt Car z carModel i numDoors
// TODO: Utwórz obiekt Motorcycle z motorcycleModel i hasSidecar
// TODO: Utwórz tablicę referencji typu Vehicle zawierającą obiekty Car i Motorcycle
// TODO: Przejdź przez tablicę i dla każdego pojazdu:
// 1. Wywołaj metodę inspect()
// 2. Użyj instanceof, aby sprawdzić, czy to Car, a następnie rzutuj na Car i wywołaj checkDoors()
// 3. Użyj instanceof, aby sprawdzić, czy to Motorcycle, a następnie rzutuj na Motorcycle i wywołaj checkSidecar()
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online