Co to jest odbicie i dlaczego jest przydatne?
Szczególnie interesuję się Javą, ale zakładam, że zasady są takie same w każdym języku.
java
reflection
terminology
Lehane
źródło
źródło
@Jailbreak
. Zapewnia bezpośredni, bezpieczny dla typu dostęp do prywatnych pól, metod itp. Pozwól kompilatorowi Java bezpiecznie zweryfikować kod i pozwól Manifoldowi wygenerować dostęp do odbicia. Dowiedz się więcej: manifold.systems/docs.html#type-safe-reflectionOdpowiedzi:
Odbicie nazwy służy do opisania kodu, który jest w stanie sprawdzić inny kod w tym samym systemie (lub samym sobie).
Załóżmy na przykład, że masz obiekt Java o nieznanym typie i chciałbyś wywołać na nim metodę „doSomething”, jeśli taka istnieje. System statycznego pisania w Javie tak naprawdę nie jest w stanie tego obsługiwać, chyba że obiekt jest zgodny ze znanym interfejsem, ale używając odbicia, twój kod może spojrzeć na obiekt i dowiedzieć się, czy ma metodę o nazwie „doSomething”, a następnie wywołać go, jeśli chcieć.
Tak więc, aby dać ci przykład tego kodu w Javie (wyobraź sobie, że przedmiotowy obiekt to foo):
Jednym z bardzo częstych przypadków użycia w Javie jest użycie z adnotacjami. Na przykład JUnit 4 użyje refleksji, aby przejrzeć twoje klasy w poszukiwaniu metod oznaczonych adnotacją @Test, a następnie wywoła je podczas uruchamiania testu jednostkowego.
Istnieje kilka dobrych przykładów refleksji na początek na stronie http://docs.oracle.com/javase/tutorial/reflect/index.html
I w końcu tak, pojęcia są bardzo podobne w innych statycznie typowanych językach, które obsługują refleksję (jak C #). W językach o typie dynamicznym opisany powyżej przypadek użycia jest mniej konieczny (ponieważ kompilator pozwoli na wywołanie dowolnej metody na dowolnym obiekcie, aw przypadku uruchomienia nie powiedzie się, jeśli nie istnieje), ale drugi przypadek szukania metod oznaczonych lub praca w określony sposób jest wciąż powszechna.
Aktualizacja z komentarza:
źródło
Method
,Constructor
,Modifier
,Field
,Member
, w zasadzie wszystko oprócz pozornieClass
) mieszczą się wjava.lang.*reflect*
opakowaniu. Być może pojęcie „refleksja” kompleksowo obejmuje zarówno „introspekcję typu”, jak i modyfikację w czasie wykonywania?Na przykład wszystkie obiekty w Javie mają metodę
getClass()
, która pozwala określić klasę obiektu, nawet jeśli nie znasz go w czasie kompilacji (np. Jeśli zadeklarowałeś go jakoObject
) - może się to wydawać trywialne, ale takie odbicie nie jest możliwe w mniej dynamicznych językach, takich jakC++
. Bardziej zaawansowane zastosowania pozwalają wyświetlać i wywoływać metody, konstruktory itp.Refleksja jest ważna, ponieważ pozwala pisać programy, które nie muszą „wiedzieć” wszystkiego w czasie kompilacji, dzięki czemu są bardziej dynamiczne, ponieważ można je ze sobą łączyć w czasie wykonywania. Kod można napisać w oparciu o znane interfejsy, ale rzeczywiste klasy, które mają być użyte, mogą zostać utworzone za pomocą odbicia od plików konfiguracyjnych.
Wiele współczesnych ram bardzo intensywnie wykorzystuje refleksję z tego właśnie powodu. Większość innych współczesnych języków również używa refleksji, a w językach skryptowych (takich jak Python) są one jeszcze ściślej zintegrowane, ponieważ wydaje się to bardziej naturalne w ogólnym modelu programowania tych języków.
źródło
C++
ma informacje o typie wykonawczym. RTTIJednym z moich ulubionych zastosowań refleksji jest poniższa metoda zrzutu Java. Bierze dowolny obiekt jako parametr i używa interfejsu API refleksji Java do wydrukowania każdej nazwy i wartości pola.
źródło
callCount
powinien być ustawiony na zero. Jego wartość służy do określenia, ile kart powinno poprzedzać każdy wiersz danych wyjściowych: za każdym razem, gdy zrzut musi zrzucić „podobiekt”, dane wyjściowe byłyby drukowane jako zagnieżdżone w obiekcie nadrzędnym. Ta metoda okazuje się przydatna, gdy jest zapakowana w inną. Zastanów sięprintDump(Object obj){ System.out.println(dump(obj, 0)); }
.Zastosowania odbicia
Odbicie jest powszechnie stosowane przez programy, które wymagają zdolności do sprawdzania lub modyfikowania działania środowiska wykonawczego aplikacji działających na maszynie wirtualnej Java. Jest to stosunkowo zaawansowana funkcja i powinna być używana tylko przez programistów, którzy dobrze znają podstawy języka. Mając to na uwadze, odbicie jest potężną techniką i może umożliwić aplikacjom wykonywanie operacji, które w innym przypadku byłyby niemożliwe.
Funkcje rozszerzalności
Aplikacja może korzystać z zewnętrznych, zdefiniowanych przez użytkownika klas, tworząc instancje obiektów rozszerzalności przy użyciu ich w pełni kwalifikowanych nazw. Przeglądarki klas i środowiska projektowania wizualnego Przeglądarka klas musi być w stanie wyliczyć członków klas. Środowiska projektowania wizualnego mogą skorzystać z korzystania z informacji o typie dostępnych w odbiciu, aby pomóc deweloperowi w pisaniu poprawnego kodu. Debugery i narzędzia testowe Debugery muszą mieć możliwość badania prywatnych członków w klasach. Wiązki testowe mogą korzystać z refleksji w celu systematycznego wywoływania interfejsów API zestawu możliwych do wykrycia zdefiniowanych w klasie, aby zapewnić wysoki poziom pokrycia kodu w zestawie testów.
Wady odbicia
Odbicie jest potężne, ale nie powinno się go używać bez rozróżnienia. Jeśli możliwe jest wykonanie operacji bez użycia odbicia, lepiej unikać jej używania. Podczas uzyskiwania dostępu do kodu za pośrednictwem refleksji należy pamiętać o następujących kwestiach.
Ponieważ odbicie obejmuje typy rozwiązywane dynamicznie, nie można wykonać niektórych optymalizacji maszyny wirtualnej Java. W rezultacie operacje odbijające mają mniejszą wydajność niż ich nieodblaskowe odpowiedniki i należy ich unikać w częściach kodu, które są często wywoływane w aplikacjach wrażliwych na wydajność.
Odbicie wymaga zezwolenia środowiska wykonawczego, które może nie być obecne podczas działania pod menedżerem bezpieczeństwa. Jest to ważne w przypadku kodu, który musi działać w ograniczonym kontekście bezpieczeństwa, takim jak aplet.
Ponieważ odbicie umożliwia kodowi wykonywanie operacji, które byłyby nielegalne w kodzie nieodblaskowym, takich jak dostęp do prywatnych pól i metod, użycie odbicia może spowodować nieoczekiwane skutki uboczne, które mogą sprawić, że kod będzie niefunkcjonalny i może zniszczyć przenośność. Kod odblaskowy łamie abstrakcje i dlatego może zmieniać zachowanie wraz z aktualizacjami platformy.
źródło: Reflection API
źródło
Refleksja jest kluczowym mechanizmem pozwalającym aplikacji lub frameworkowi na pracę z kodem, który mógł nawet jeszcze nie zostać napisany!
Weźmy na przykład typowy plik web.xml. Będzie zawierać listę elementów serwletu, które zawierają zagnieżdżone elementy klasy serwletu. Kontener serwletu przetworzy plik web.xml i utworzy nowe wystąpienie każdej klasy serwletu poprzez odbicie.
Innym przykładem może być Java API for XML Parsing (JAXP) . Gdzie dostawca parsera XML jest „podłączony” przez dobrze znane właściwości systemu, które są używane do konstruowania nowych instancji poprzez odbicie.
I wreszcie, najbardziej wszechstronnym przykładem jest Wiosna, która wykorzystuje odbicie do tworzenia swoich ziaren i do intensywnego korzystania z serwerów proxy
źródło
Nie każdy język obsługuje refleksję, ale zasady są zwykle takie same w językach, które go obsługują.
Refleksja to zdolność „refleksji” nad strukturą twojego programu. Lub bardziej konkretnie. Aby spojrzeć na posiadane obiekty i klasy i programowo uzyskać informacje o metodach, polach i interfejsach, które implementują. Możesz także patrzeć na takie rzeczy jak adnotacje.
Przydaje się w wielu sytuacjach. Wszędzie, gdzie chcesz mieć możliwość dynamicznego podłączania klas do swojego kodu. Wiele relacyjnych maperów obiektowych używa refleksji, aby móc tworzyć instancje obiektów z baz danych, nie wiedząc z góry, z jakich obiektów będą korzystać. Architektury wtyczek to kolejne miejsce, w którym przydatne jest odbicie. W takich sytuacjach ważna jest możliwość dynamicznego ładowania kodu i określania, czy istnieją typy, które implementują odpowiedni interfejs do użycia jako wtyczka.
źródło
Odbicie pozwala na tworzenie instancji nowych obiektów, wywoływanie metod oraz pobieranie / ustawianie operacji na zmiennych klasowych dynamicznie w czasie wykonywania bez wcześniejszej wiedzy o ich implementacji.
W powyższym przykładzie parametr null jest obiektem, na którym chcesz wywołać metodę. Jeśli metoda jest statyczna, podajesz null. Jeśli metoda nie jest statyczna, wówczas podczas wywoływania należy podać poprawną instancję MyObject zamiast wartości null.
Refleksja pozwala również na dostęp do prywatnego członka / metod klasy:
.
java.lang.reflect
). Dostęp do metadanych klasy można uzyskać poprzezjava.lang.Class
.Odbicie jest bardzo potężnym API, ale może spowolnić aplikację, jeśli zostanie użyte w nadmiarze, ponieważ rozwiązuje wszystkie typy w czasie wykonywania.
źródło
Java Reflection jest dość potężny i może być bardzo przydatny. Java Reflection umożliwia sprawdzanie klas, interfejsów, pól i metod w czasie wykonywania, bez znajomości nazw klas, metod itp. W czasie kompilacji. Możliwe jest także tworzenie instancji nowych obiektów, wywoływanie metod i pobieranie / ustawianie wartości pól za pomocą odbicia.
Szybki przykład Java Reflection pokazujący, jak wygląda użycie odbicia:
Ten przykład uzyskuje obiekt Class z klasy o nazwie MyObject. Korzystając z obiektu klasy, przykład otrzymuje listę metod w tej klasie, iteruje metody i wypisuje ich nazwy.
Dokładnie wyjaśniono, jak to wszystko działa
Edycja : Po prawie 1 roku edytuję tę odpowiedź, ponieważ podczas czytania o refleksji mam jeszcze kilka zastosowań Refleksji.
Kiedy kontekst Spring przetwarza ten element <bean>, użyje Class.forName (String) z argumentem „com.example.Foo”, aby utworzyć instancję tej klasy.
Następnie ponownie użyje refleksji, aby uzyskać odpowiedni setter dla elementu <property> i ustawić jego wartość na określoną wartość.
W przypadku metod prywatnych
W przypadku pól prywatnych
źródło
Przykład:
Weźmy na przykład aplikację zdalną, która nadaje aplikacji obiekt uzyskany za pomocą jej metod API. Teraz na podstawie obiektu może być konieczne wykonanie jakiegoś obliczenia.
Dostawca gwarantuje, że obiekt może być 3 typów i musimy wykonać obliczenia na podstawie tego, jaki typ obiektu.
Możemy więc zaimplementować w 3 klasach, z których każda zawiera inną logikę. Oczywiście informacje o obiekcie są dostępne w środowisku wykonawczym, więc nie można statycznie kodować w celu wykonania obliczeń, dlatego odbicie jest używane do utworzenia obiektu klasy, który jest wymagany do wykonania obliczeń na podstawie obiekt otrzymany od dostawcy.
źródło
instanceof
do określenia typu obiektu w czasie wykonywania?Prosty przykład do refleksji. W grze w szachy nie wiesz, co użytkownik poruszy w czasie wykonywania. refleksji można używać do wywoływania metod, które są już zaimplementowane w czasie wykonywania:
źródło
Refleksja to interfejs API służący do sprawdzania lub modyfikowania zachowania metod, klas i interfejsów w czasie wykonywania.
java.lang.reflect package
.java.lang
Ijava.lang.reflect
pakietach klas Java refleksji.Refleksji można użyć do uzyskania informacji o -
Klasa
getClass()
metoda jest stosowana, aby uzyskać nazwę klasy, do której obiekt należy.Konstruktorzy
getConstructors()
metoda jest stosowana w celu uzyskania konstruktorów publicznych klasy, do której obiekt należy.Metody
getMethods()
metoda jest stosowana w celu uzyskania publicznych metod klasy, do której obiekty należy.Odbicie API stosuje się głównie:
IDE (zintegrowane środowisko programistyczne), np. Eclipse, MyEclipse, NetBeans itp.
Narzędzia do debugowania i testowania itp.
Zalety używania Refleksji:
Funkcje rozszerzalności: aplikacja może korzystać z zewnętrznych klas zdefiniowanych przez użytkownika, tworząc instancje obiektów rozszerzalności przy użyciu ich w pełni kwalifikowanych nazw.
Narzędzia do debugowania i testowania: Debugery używają właściwości refleksji do badania prywatnych członków klas.
Wady:
Narzut wydajności: Operacje odbijające mają niższą wydajność niż ich nieodblaskowe odpowiedniki i należy ich unikać w częściach kodu, które są często wywoływane w aplikacjach wrażliwych na wydajność.
Ujawnienie elementów wewnętrznych: kod odblaskowy łamie abstrakcje i dlatego może zmieniać zachowanie w przypadku aktualizacji platformy.
Ref: Java Reflection javarevisited.blogspot.in
źródło
Zgodnie z moim zrozumieniem:
Odbicie pozwala programiście na dynamiczny dostęp do elementów w programie. tzn. podczas kodowania aplikacji, jeśli programista nie wie o klasie lub jej metodach, może dynamicznie korzystać z takiej klasy (w czasie wykonywania) za pomocą odbicia.
Jest często używany w scenariuszach, w których nazwa klasy często się zmienia. Jeśli taka sytuacja się pojawi, programista ma trudności z przepisaniem aplikacji i zmienianiem nazwy klasy raz po raz.
Zamiast tego, używając refleksji, trzeba się martwić o ewentualną zmianę nazwy klasy.
źródło
Refleksja to zestaw funkcji, który umożliwia dostęp do informacji o środowisku wykonawczym programu i modyfikowanie jego zachowania (z pewnymi ograniczeniami).
Jest to przydatne, ponieważ pozwala zmienić zachowanie środowiska wykonawczego w zależności od meta informacji twojego programu, tzn. Możesz sprawdzić typ zwracanej funkcji i zmienić sposób obsługi sytuacji.
Na przykład w języku C # można załadować zestaw (a .dll) w środowisku wykonawczym i zbadać go, poruszając się po klasach i podejmując działania zgodnie z tym, co znalazłeś. Pozwala także utworzyć instancję klasy w środowisku wykonawczym, wywołać jej metodę itp.
Gdzie to może być przydatne? Nie jest przydatny za każdym razem, ale w konkretnych sytuacjach. Na przykład możesz go użyć do uzyskania nazwy klasy do celów logowania, do dynamicznego tworzenia procedur obsługi zdarzeń zgodnie z tym, co podano w pliku konfiguracyjnym i tak dalej ...
źródło
Chcę tylko dodać trochę do wszystkiego, co było na liście.
Z Reflection API możesz napisać uniwersalną
toString()
metodę dla dowolnego obiektu.Jest to przydatne podczas debugowania.
Oto przykład:
źródło
Odbicie ma pozwolić obiektowi zobaczyć ich wygląd. Ten argument wydaje się nie mieć nic wspólnego z refleksją. W rzeczywistości jest to umiejętność „samoidentyfikacji”.
Samo odbicie jest słowem dla takich języków, które nie mają zdolności do samowiedzy i wyczuwania, takich jak Java i C #. Ponieważ nie mają możliwości samowiedzy, kiedy chcemy obserwować, jak to wygląda, musimy mieć jeszcze jedną rzecz do przemyślenia, jak to wygląda. Doskonałe języki dynamiczne, takie jak Ruby i Python, potrafią postrzegać swoje własne odbicie bez pomocy innych osób. Można powiedzieć, że obiekt Java nie może postrzegać tego, jak wygląda bez lustra, które jest przedmiotem klasy odbicia, ale obiekt w Pythonie może postrzegać go bez lustra. Dlatego potrzebujemy refleksji w Javie.
źródło
Ze strony dokumentacji Java
AccessibleObject
umożliwia zniesienie kontroli dostępu, jeśli jestReflectPermission
to konieczne .Klasy w tym pakiecie, wraz z
java.lang.Class
aplikacjami, takimi jak debuggery, interpretatory, inspektory obiektów, przeglądarki klas i usługi, takie jakObject Serialization
i,JavaBeans
które potrzebują dostępu do publicznych członków obiektu docelowego (na podstawie jego klasy środowiska wykonawczego) lub członków zadeklarowanych przez dana klasaObejmuje następujące funkcje.
Zajrzyj do tego łącza do dokumentacji metod ujawnionych przez
Class
klasę.Z tego artykułu (Dennis Sosnoski, prezes, Sosnoski Software Solutions, Inc) i tego artykułu (eksploracja zabezpieczeń pdf):
Widzę znaczące wady niż zastosowania używania Reflection
Użytkownik refleksji:
Wady refleksji:
Ogólne nadużycia:
Spójrz na to pytanie SE dotyczące nadużywania funkcji refleksji:
Jak odczytać prywatne pole w Javie?
Podsumowanie:
Niepewne korzystanie z jego funkcji przeprowadzane z poziomu kodu systemowego może również łatwo doprowadzić do kompromisu w trybie bezpieczeństwa Java l. Dlatego używaj tej funkcji oszczędnie
źródło
Woozle
poproszenie klasy o sprawdzenie innych klas podczas uruchamiania, aby zobaczyć, które z nich mająRegisterAsWoozleHelper()
metodę statyczną , i wywołanie wszystkich takich metod za pomocą wywołania zwrotnego, którego mogą użyć, aby powiedziećWoozle
o sobie, unikając trzeba użyć Reflection podczas np. deserializacji danych.Jak sama nazwa wskazuje, odzwierciedla to, co posiada, na przykład metodę klasową itp. Oprócz zapewnienia funkcji do wywoływania metody tworzenia instancji dynamicznie w czasie wykonywania.
Jest używany przez wiele platform i aplikacji pod drzewem do wywoływania usług bez faktycznej znajomości kodu.
źródło
Refleksja daje możliwość napisania bardziej ogólnego kodu. Umożliwia tworzenie obiektu w czasie wykonywania i wywoływanie jego metody w czasie wykonywania. Dzięki temu program może zostać sparametryzowany. Umożliwia także introspekcję obiektu i klasy w celu wykrycia jego zmiennych i metody wystawionej na świat zewnętrzny.
źródło
Reflection
ma wiele zastosowań . Ten, który znam bardziej, to możliwość tworzenia kodu w locie.źródło
Chcę odpowiedzieć na to pytanie za pomocą przykładu. Przede wszystkim
Hibernate
projekt wykorzystujeReflection API
do generowaniaCRUD
instrukcji w celu połączenia przepaści między uruchomioną aplikacją a magazynem trwałości. Kiedy coś się zmienia w domenie,Hibernate
musi wiedzieć o nich, aby zachować je w magazynie danych i odwrotnie.Alternatywnie działa
Lombok Project
. Po prostu wstrzykuje kod w czasie kompilacji, co powoduje wstawianie kodu do klas domeny. (Myślę, że to jest w porządku dla pobierających i ustawiających)Hibernate
wybrał,reflection
ponieważ ma minimalny wpływ na proces kompilacji aplikacji.A od Java 7 mamy
MethodHandles
, który działa jakoReflection API
. W projektach do pracy z rejestratorami wystarczy skopiować i wkleić następny kod:Ponieważ w tym przypadku trudno jest popełnić błąd literowy.
źródło
Uważam, że najlepiej jest wyjaśnić na przykładzie, a żadna z odpowiedzi nie wydaje się, aby to zrobić ...
Praktycznym przykładem użycia odbić może być Java Language Server napisany w Javie lub PHP Language Server napisany w PHP itp. Language Server daje możliwości IDE, takie jak autouzupełnianie, przejście do definicji, pomoc kontekstowa, typy podpowiedzi i wiele innych. Aby mieć wszystkie nazwy znaczników (słowa, które można uzupełniać automatycznie), aby wyświetlały wszystkie możliwe dopasowania podczas pisania, serwer językowy musi sprawdzać wszystko o klasie, w tym bloki dokumentów i członków prywatnych. W tym celu potrzebuje odzwierciedlenia wspomnianej klasy.
Innym przykładem może być test jednostkowy metody prywatnej. Jednym ze sposobów jest utworzenie refleksji i zmiana zakresu metody na publiczną w fazie konfiguracji testu. Oczywiście można argumentować, że prywatne metody nie powinny być testowane bezpośrednio, ale nie o to chodzi.
źródło