Jestem nowy w Javie; poprzez moje badania przeczytałem, że refleksja służy do wywoływania klas i metod oraz do poznania, które metody są wdrożone, czy nie.
Kiedy powinienem używać odbicia i jaka jest różnica między używaniem odbicia i tworzeniem obiektów i metodami wywoływania w tradycyjny sposób?
java
reflection
Hamzah khammash
źródło
źródło
Odpowiedzi:
Odbicie jest znacznie wolniejsze niż tylko wywoływanie metod według ich nazw, ponieważ musi sprawdzać metadane w kodzie bajtowym zamiast po prostu używać wstępnie skompilowanych adresów i stałych.
Odbicie jest również silniejsze: możesz odzyskać definicję elementu
protected
lubfinal
elementu, usunąć ochronę i manipulować nią tak, jakby została uznana za zmienną! Oczywiście podważa to wiele gwarancji, jakie język zwykle zapewnia twoim programom i może być bardzo, bardzo niebezpieczne.I to właściwie wyjaśnia, kiedy go używać. Zwykle nie. Jeśli chcesz wywołać metodę, po prostu ją wywołaj. Jeśli chcesz zmutować członka, po prostu zadeklaruj, że jest on zmienny, zamiast iść za plecami kompilacji.
Jednym z użytecznych zastosowań refleksji w świecie rzeczywistym jest pisanie frameworka, który musi współdziałać z klasami zdefiniowanymi przez użytkownika, w których autor frameworku nie wie, czym będą członkowie (a nawet klasy). Refleksja pozwala im radzić sobie z dowolną klasą, nie wiedząc o tym wcześniej. Na przykład nie sądzę, że bez refleksji byłoby możliwe napisanie złożonej biblioteki zorientowanej na aspekty.
Jako inny przykład, JUnit użył trywialnego fragmentu refleksji: wylicza wszystkie metody w twojej klasie, zakłada, że wszystkie te wywoływane
testXXX
są metodami testowymi i wykonuje tylko te. Ale można to teraz zrobić lepiej za pomocą adnotacji, aw rzeczywistości JUnit 4 w dużej mierze przeniósł się do adnotacji.źródło
Byłem kiedyś taki jak ty, nie wiedziałem wiele o refleksji - wciąż nie - ale użyłem go raz.
Miałem klasę z dwiema klasami wewnętrznymi i każda klasa miała wiele metod.
Musiałem wywołać wszystkie metody z klasy wewnętrznej, a ręczne wywołanie ich byłoby zbyt dużym nakładem pracy.
Używając refleksji, mogłem wywołać wszystkie te metody w zaledwie 2-3 wierszach kodu, zamiast liczby samych metod.
źródło
Pogrupowałbym zastosowania refleksji na trzy grupy:
źródło
Odbicie pozwala programowi na pracę z kodem, który może nie być obecny, i robi to w niezawodny sposób.
„Normalny kod” ma takie fragmenty,
URLConnection c = null
które przez samą swoją obecność powodują, że moduł ładujący klasy ładuje klasę URLConnection w ramach ładowania tej klasy, zgłaszając wyjątek ClassNotFound i kończąc działanie.Odbicie umożliwia ładowanie klas na podstawie ich nazw w postaci ciągów i testowanie ich pod kątem różnych właściwości (przydatne w wielu wersjach poza kontrolą) przed uruchomieniem rzeczywistych klas, które są od nich zależne. Typowym przykładem jest kod specyficzny dla OS X używany do nadawania programom Java wyglądu natywnego w systemie OS X, które nie są obecne na innych platformach.
źródło
Zasadniczo refleksja oznacza użycie kodu programu jako danych.
Dlatego użycie refleksji może być dobrym pomysłem, gdy kod programu jest użytecznym źródłem danych. (Ale są kompromisy, więc nie zawsze może to być dobry pomysł).
Rozważmy na przykład prostą klasę:
i chcesz z niego wygenerować XML. Możesz napisać kod do wygenerowania XML:
Ale to dużo kodu z podstawowymi danymi i za każdym razem, gdy zmieniasz klasę, musisz aktualizować kod. Naprawdę możesz opisać, co robi ten kod jako
To jest algorytm, a dane wejściowe algorytmu to klasa: potrzebujemy jego nazwy oraz nazw, typów i wartości jego właściwości. Tu pojawia się refleksja: daje dostęp do tych informacji. Java pozwala sprawdzać typy przy użyciu metod
Class
klasy.Kilka innych przypadków użycia:
Jednak pełne odzwierciedlenie oznacza nie tylko spojrzenie na istniejący kod (który sam w sobie jest znany jako „introspekcja”), ale także modyfikowanie lub generowanie kodu. W tym celu istnieją dwa znaczące przypadki użycia w Javie: serwery proxy i makiety.
Powiedzmy, że masz interfejs:
i masz implementację, która robi coś interesującego:
W rzeczywistości masz też drugą implementację:
Teraz potrzebujesz także danych wyjściowych dziennika; po prostu chcesz komunikat dziennika za każdym razem, gdy wywoływana jest metoda. Możesz jawnie dodać dane wyjściowe dziennika do każdej metody, ale byłoby to irytujące i musiałbyś to zrobić dwa razy; raz na każde wdrożenie. (A więc jeszcze więcej, jeśli dodasz więcej implementacji).
Zamiast tego możesz napisać proxy:
Ponownie jednak istnieje powtarzalny wzorzec, który można opisać algorytmem:
a wejściem tego algorytmu jest definicja interfejsu.
Refleksja pozwala zdefiniować nową klasę za pomocą tego algorytmu. Java pozwala to zrobić przy użyciu metod
java.lang.reflect.Proxy
klasy, a istnieją biblioteki, które dają jeszcze więcej mocy.Jakie są wady refleksji?
źródło
Odbicie może automatycznie utrzymywać synchronizację części twojego programu, gdzie wcześniej musiałbyś ręcznie zaktualizować swój program, aby używał nowych interfejsów.
źródło