Historia pytania:
Słowo kluczowe instanceof pojawiło się w Javie w celu sprawdzenia, czy obiekt należy do określonego typu lub jego podtypu. Mechanizm umożliwił w czasie działania (runtime) precyzowanie typu obiektu, co jest istotne dla pracy z generycznymi kolekcjami, polimorfizmem i rzutowaniem typów.
Problem:
Bez poprawnego określenia typu obiektu mogą wystąpić błędy ClassCastException lub niepoprawne przetwarzanie logiki w gałęziach kodu, jeśli przeprowadza się rzutowanie typów bez sprawdzania. Nadmierne używanie instanceof często jest oznaką nieudanej architektury.
Rozwiązanie:
instanceof zwraca true, jeśli obiekt jest instancją danego klasy lub dowolnego jego podklasy, lub implementuje interfejs. W Javie 16 wprowadzono dopasowywanie wzorców z automatycznym rzutowaniem typu w bloku if.
Przykład kodu:
Object obj = "Hello!"; if (obj instanceof String) { String s = (String) obj; // Rzutowanie jest bezpieczne System.out.println(s.length()); }
Od Javy 16:
if (obj instanceof String s) { System.out.println(s.length()); // s automatycznie rzutowane na String }
Kluczowe cechy:
null instanceof Type zawsze zwraca false)Co zwróci null instanceof SomeClass?
Zawsze false. Operator gwarantuje, że jeśli obiekt to null, wynik to false, eliminując NullPointerException.
Czy można używać instanceof z typami generycznymi, np. if (obj instanceof List<String>)?
Nie. Z powodu wymazywania typów (type erasure) nie można sprawdzać parametrów generycznych w czasie działania. Sprawdzanie zawsze odbywa się tylko na typie raw (np. List).
Przykład kodu:
List<String> list = ...; if (list instanceof List<String>) { ... } // Błąd kompilacji if (list instanceof List) { ... } // Dozwolone
Czy użycie instanceof może wskazywać na problemy w projektowaniu kodu?
Tak. Ciągłe używanie instanceof zamiast zastosowania abstrakcji lub wzorców (np. wzorzec Visitor) często wskazuje na naruszenie zasad OOP, takich jak zasada otwartości/zamkniętości.
W metodzie występuje duża sekwencja if-else z sprawdzeniem wszystkich możliwych podklas jednej superklasy przez instanceof, a w każdej gałęzi — rzutowanie typu i wywołanie odpowiedniej metody.
Zalety:
Wady:
Zamiast if-else zrealizowano wzorzec Visitor: każda podklasa ma metodę wywołującą odpowiednie zachowanie, co eliminuje potrzebę używania instanceof.
Zalety:
Wady: