Historia pytania
Operator instanceof został wprowadzony w Javie, aby umożliwić sprawdzenie, czy obiekt należy do określonego typu (klasy lub interfejsu) przed rzutowaniem typów. Stało się to istotne w pracy z dziedziczeniem, polimorfizmem i obsługą heterogenicznych kolekcji obiektów.
Problem
Bez sprawdzenia przynależności do typu można otrzymać ClassCastException podczas rzutowania typów. Niewłaściwe użycie instanceof może pogorszyć architekturę kodu, prowadząc do antywzorów (na przykład częste użycie zamiast polimorfizmu).
Rozwiązanie
Operator instanceof zwraca true, jeśli obiekt nie jest null i należy do sprawdzanego typu lub implementuje dany interfejs.
Przykład kodu:
Object obj = "Hello"; if (obj instanceof String) { String str = (String) obj; System.out.println(str.toUpperCase()); }
Kluczowe cechy:
Co zwróci obj instanceof SomeClass, jeśli obj == null?
instanceof zawsze zwraca false, jeśli obiekt jest null, niezależnie od sprawdzanego typu. Jest to istotne dla zapobiegania NullPointerException.
Czy można używać instanceof do sprawdzenia przynależności do interfejsu?
Tak. instanceof jest używane do sprawdzenia, czy obiekt implementuje potrzebny interfejs, a nie tylko przynależność do określonej klasy.
Przykład kodu:
Runnable r = () -> {}; System.out.println(r instanceof Runnable); // true
Co się stanie, jeśli klasa jest kompilowana z --release 16+ i dopasowanie wzorców dla instanceof już zostało wdrożone?
Od Java 16+ operator instanceof obsługuje dopasowanie wzorców, co oznacza, że można od razu w sprawdzeniu wskazać zmienną i uniknąć jawnego rzutowania.
Przykład kodu:
Object obj = "Test string"; if (obj instanceof String str) { System.out.println(str.length()); }
W dużym projekcie logikę przetwarzania biznesowego budowano na serii if (obj instanceof X)... zamiast przez nadpisanie metod. Utrudniło to konserwację: pojawienie się nowego typu wymagało zmiany wszystkich sprawdzeń.
Zalety:
Wady:
W podobnym projekcie dla rozszerzalnej hierarchii używano abstrakcyjnych metod, a instanceof tylko do sprawdzenia szczególnych edge-case'ów.
Zalety:
Wady: