java reflection tutorial with examples
Ten samouczek wideo wyjaśnia, czym jest odbicie i jak go zaimplementować za pomocą interfejsu API Reflection:
Odbicie w Javie polega na sprawdzeniu i zmianie zachowania programu w czasie wykonywania.
Za pomocą tego interfejsu API odbicia można sprawdzać klasy, konstruktory, modyfikatory, pola, metody i interfejsy w czasie wykonywania. Na przykład, możesz uzyskać nazwę klasy lub szczegółowe informacje na temat prywatnych członków klasy.
Przeczytaj całą naszą Seria szkoleń JAVA aby uzyskać więcej informacji na temat koncepcji języka Java.
Oto samouczek wideo na temat Java Reflection:
Czego się nauczysz:
Odbicie w Javie
Zdajemy sobie sprawę, że w danej klasie możemy modyfikować jej właściwości i metody w czasie kompilacji i jest to bardzo proste. Niezależnie od tego, czy właściwości i metody są anonimowe, czy mają nazwy, można je dowolnie zmieniać w czasie kompilacji.
Ale nie możemy zmieniać tych klas, metod ani pól w czasie wykonywania w locie. Innymi słowy, bardzo trudno jest zmienić zachowanie różnych komponentów programistycznych w czasie wykonywania, szczególnie w przypadku nieznanych obiektów.
Język programowania Java udostępnia funkcję o nazwie 'Odbicie' co pozwala nam modyfikować zachowanie klasy, pola lub metody w czasie wykonywania.
W ten sposób odbicie można zdefiniować jako „Technika sprawdzania i modyfikowania zachowania nieznanego obiektu w czasie wykonywania. Obiekt może być klasą, polem lub metodą ”.
Reflection to „Interfejs programowania aplikacji” (API) dostarczany przez Javę.
Proces „Refleksji” został przedstawiony poniżej.
Na powyższym przedstawieniu widzimy, że mamy nieznany obiekt. Następnie używamy API Reflection na tym obiekcie. W rezultacie możemy modyfikować zachowanie tego obiektu w czasie wykonywania.
W ten sposób możemy używać API Reflection w naszych programach w celu modyfikowania zachowania obiektu. Obiekty mogą być dowolnymi metodami, interfejsami, klasami, itp. Sprawdzamy te obiekty, a następnie zmieniamy ich zachowanie w czasie wykonywania za pomocą refleksyjnego API.
W Javie „java.lang” i „java.lang.reflect” to dwa pakiety, które zapewniają klasy do refleksji. Specjalna klasa „java.lang.Class” udostępnia metody i właściwości do wyodrębniania metadanych, za pomocą których możemy sprawdzać i modyfikować zachowanie klasy.
Używamy API Reflection dostarczonego przez powyższe pakiety do modyfikowania klasy i jej elementów członkowskich, w tym pól, metod, konstruktorów itp. W czasie wykonywania. Cechą wyróżniającą Reflection API jest to, że możemy również manipulować prywatnymi składowymi danych lub metodami klasy.
Interfejs API Reflection jest używany głównie w:
- Odbicie jest używane głównie w narzędziach do debugowania, JUnit i strukturach do sprawdzania i zmiany zachowania w czasie wykonywania.
- IDE (zintegrowane środowisko programistyczne) Na przykład. Eclipse IDE, NetBeans itp.
- Narzędzia testowe itp.
- Jest używany, gdy aplikacja ma biblioteki innych firm i gdy chcesz dowiedzieć się o dostępnych klasach i metodach.
Reflection API w Javie
Wykorzystując Reflection API możemy zaimplementować refleksję na następujących encjach:
- Pole : Klasa Field zawiera informacje, których używamy do deklarowania zmiennej lub pola, takiego jak typ danych (int, double, String itp.), Modyfikator dostępu (private, public, protected itp.), Nazwę (identyfikator) i wartość.
- metoda : Klasa Method może nam pomóc w wyodrębnieniu informacji, takich jak modyfikator dostępu do metody, typ zwracanej metody, nazwa metody, typy parametrów metody i typy wyjątków zgłaszane przez metodę.
- Budowniczy : Constructor zawiera informacje o konstruktorze klasy, który zawiera modyfikator dostępu do konstruktora, nazwę konstruktora i typy parametrów.
- Edytować : Modifier - klasa zawiera informacje o określonym modyfikatorze dostępu.
Wszystkie powyższe klasy są częścią pakietu java.lang.reflect. Następnie omówimy każdą z tych klas i użyjemy przykładów programowania, aby zademonstrować refleksję na temat tych klas.
Zacznijmy od klasy java.lang.Class.
java.lang.Class Klasa
Klasa java.lang.The zawiera wszystkie informacje i dane o klasach i obiektach w czasie wykonywania. To jest główna klasa używana do refleksji.
Klasa java.lang.Class zapewnia:
- Metody pobierania metadanych klas w czasie wykonywania.
- Metody do sprawdzania i modyfikowania zachowania klasy w czasie wykonywania.
Utwórz obiekty java.lang.Class
Możemy tworzyć obiekty java.lang.Class używając jednej z poniższych opcji.
pytania do wywiadu dotyczącego unixa dla programistów Java
# 1) .class rozszerzenie
Pierwszą opcją tworzenia obiektu Class jest użycie rozszerzenia .class.
Na przykład,jeśli Test jest klasą, możemy utworzyć obiekt Class w następujący sposób:
Class obj_test = Test.class;
Następnie możemy użyć obj_test do wykonania odbicia, ponieważ ten obiekt będzie zawierał wszystkie informacje o klasie Test.
# 2) forName ()
forName () przyjmuje nazwę klasy jako argument i zwraca obiekt Class.
Na przykład,obiekt klasy Test można utworzyć w następujący sposób:
class obj_test = Class.forName (“Test”);
# 3) metoda getClas ()
Metoda getClass () używa obiektu klasy do pobrania obiektu java.lang.Class.
Na przykład,rozważ następujący fragment kodu:
Test obj = new Test (); Class obj_test = obj.getClass ();
W pierwszej linii utworzyliśmy obiekt klasy Test. Następnie za pomocą tego obiektu wywołaliśmy metodę „getClass ()”, aby uzyskać obiekt obj_test z klasy java.lang.Class.
Uzyskaj superklasy i modyfikatory dostępu
java.lang.class udostępnia metodę „getSuperClass ()”, która jest używana do uzyskiwania nadklasy dowolnej klasy.
Podobnie, udostępnia metodę getModifier (), która zwraca modyfikator dostępu klasy.
Poniższy przykład ilustruje metodę getSuperClass ().
import java.lang.Class; import java.lang.reflect.*; //define Person interface interface Person { public void display(); } //declare class Student that implements Person class Student implements Person { //define interface method display public void display() { System.out.println('I am a Student'); } } class Main { public static void main(String() args) { try { // create an object of Student class Student s1 = new Student(); // get Class object using getClass() Class obj = s1.getClass(); // get the superclass of Student Class superClass = obj.getSuperclass(); System.out.println('Superclass of Student Class: ' + superClass.getName()); } catch(Exception e) { e.printStackTrace(); } } }
Wynik
W powyższym przykładzie programowania interfejs Person jest zdefiniowany za pomocą samotnej metody „display ()”. Następnie definiujemy klasę Student implementującą interfejs osoby. W metodzie głównej używamy metody getClass () do pobierania obiektu Class, a następnie uzyskujemy dostęp do obiektu nadrzędnego lub nadklasy obiektu Student za pomocą metody getSuperClass ().
Pobierz interfejsy
Jeśli klasa implementuje jakieś interfejsy, możemy uzyskać nazwy tych interfejsów za pomocą metody getInterfaces () z klasy java.lang.Class. W tym celu musimy przeprowadzić refleksję na temat klasy Java.
Poniższy przykład programowania przedstawia użycie metody getInterfaces () w Java Reflection.
import java.lang.Class; import java.lang.reflect.*; //define Interface Animals and PetAnimals interface Animals { public void display(); } interface PetAnimals { public void makeSound(); } //define a class Dog that implements above interfaces class Dog implements Animals, PetAnimals { //define interface method display public void display() { System.out.println('This is a PetAnimal::Dog'); } //define interface method makeSound public void makeSound() { System.out.println('Dog makes sound::Bark bark'); } } class Main { public static void main(String() args) { try { // create an object of Dog class Dog dog = new Dog(); // get class object Class obj = dog.getClass(); // get the interfaces implemented by Dog Class() objInterface = obj.getInterfaces(); System.out.println('Class Dog implements following interfaces:'); //print all the interfaces implemented by class Dog for(Class citem : objInterface) { System.out.println('Interface Name: ' + citem.getName()); } } catch(Exception e) { e.printStackTrace(); } } }
Wynik
W powyższym programie zdefiniowaliśmy dwa interfejsy tj. Animals i PetAnimals. Następnie definiujemy klasę Dog, która implementuje oba te interfejsy.
W metodzie głównej pobieramy obiekt klasy Dog w java.lang.Class w celu wykonania refleksji. Następnie używamy metody getInterfaces (), aby pobrać interfejsy, które są implementowane przez klasę Dog.
Odbicie: Uzyskaj wartość pola
Jak już wspomniano, pakiet java.lang.reflect udostępnia klasę Field, która pomaga nam odzwierciedlić pole lub elementy składowe danych klasy.
Poniżej wymieniono metody zapewniane przez klasę Field dla odbicia pola.
metoda | Opis |
---|---|
getField („nazwa_pola”) | Zwraca pole (publiczne) o określonej nazwie pola. |
getFields () | Zwraca wszystkie pola publiczne (zarówno dla klasy, jak i nadklasy). |
getDeclaredFields () | Pobiera wszystkie pola klasy. |
getModifier () | Zwraca całkowitą reprezentację modyfikatora dostępu do pola. |
set (classObject, wartość) | Przypisuje określoną wartość do pola. |
get (classObject) | Pobiera wartość pola. |
setAccessible (boolean) | Udostępnij pole prywatne, przekazując wartość true. |
getDeclaredField („nazwa_pola”) | Zwraca pole o określonej nazwie. |
Poniżej podano dwa przykłady refleksji, które pokazują refleksję na polu publicznym i prywatnym.
Poniższy program w języku Java demonstruje refleksję na temat pola publicznego.
import java.lang.Class; import java.lang.reflect.*; class Student { public String StudentName; } class Main { public static void main(String() args) { try{ Student student = new Student(); // get an object of the class Class Class obj = student.getClass(); // provide field name and get the field info Field student_field = obj.getField('StudentName'); System.out.println('Details of StudentName class field:'); // set the value of field student_field.set(student, 'Lacey'); // get the access modifier of StudentName int mod1 = student_field.getModifiers(); String modifier1 = Modifier.toString(mod1); System.out.println('StudentName Modifier::' + modifier1); // get the value of field by converting in String String typeValue = (String)student_field.get(student); System.out.println('StudentName Value::' + typeValue); } catch(Exception e) { e.printStackTrace(); } } }
Wynik
W tym programie zadeklarowaliśmy klasę „Student” z publicznym polem StudentName. Następnie za pomocą interfejsu API klasy Field dokonujemy refleksji nad polem StudentName i pobieramy jego modyfikator dostępu oraz wartość.
Następny program dokonuje refleksji na prywatnym polu zajęć. Operacje są podobne, z tym wyjątkiem, że istnieje jedno dodatkowe wywołanie funkcji dla pola prywatnego. Musimy wywołać setAccessible (true) dla pola prywatnego. Następnie dokonujemy refleksji na tym polu w podobny sposób, jak na polu publicznym.
import java.lang.Class; import java.lang.reflect.*; class Student { private String rollNo; } class Main { public static void main(String() args) { try { Student student = new Student(); // get the object for class Student in a Class. Class obj = student.getClass(); // access the private field Field field2 = obj.getDeclaredField('rollNo'); // make the private field accessible field2.setAccessible(true); // set the value of rollNo field2.set(student, '27'); System.out.println('Field Information of rollNo:'); // get the access modifier of rollNo int mod2 = field2.getModifiers(); String modifier2 = Modifier.toString(mod2); System.out.println('rollNo modifier::' + modifier2); // get the value of rollNo converting in String String rollNoValue = (String)field2.get(student); System.out.println('rollNo Value::' + rollNoValue); } catch(Exception e) { e.printStackTrace(); } } }
Wynik
Refleksja: metoda
Podobnie jak w przypadku pól klasy, możemy również dokonać refleksji na temat metod klas i zmodyfikować ich zachowanie w czasie wykonywania. W tym celu używamy klasy Method pakietu java.lang.reflect.
Poniżej wymieniono funkcje zapewniane przez klasę Method dla odbicia metody klasy.
metoda | Opis |
---|---|
getMethods () | Pobiera wszystkie metody publiczne zdefiniowane w klasie i jej nadklasie. |
getDeclaredMethod () | Zwraca metody zadeklarowane w klasie. |
getName () | Zwraca nazwy metod. |
getModifiers () | Zwraca reprezentację całkowitą modyfikatora dostępu metody. |
getReturnType () | Zwraca typ zwracanej metody. |
Poniższy przykład pokazuje odbicie metod klas w Javie przy użyciu powyższych interfejsów API.
import java.lang.Class; import java.lang.reflect.*; //declare a class Vehicle with four methods class Vehicle { public void display() { System.out.println('I am a Vehicle!!'); } protected void start() { System.out.println('Vehicle Started!!!'); } protected void stop() { System.out.println('Vehicle Stopped!!!'); } private void serviceVehicle() { System.out.println('Vehicle serviced!!'); } }class Main { public static void main(String() args) { try { Vehicle car = new Vehicle(); // create an object of Class Class obj = car.getClass(); // get all the methods using the getDeclaredMethod() in an array Method() methods = obj.getDeclaredMethods(); // for each method get method info for(Method m : methods) { System.out.println('Method Name: ' + m.getName()); // get the access modifier of methods int modifier = m.getModifiers(); System.out.print('Modifier: ' + Modifier.toString(modifier) + ' '); // get the return type of method System.out.print('Return Type: ' + m.getReturnType()); System.out.println('
'); } } catch(Exception e) { e.printStackTrace(); } } }
Wynik
W powyższym programie widzimy, że metoda getDeclaredMethods zwraca tablicę metod zadeklarowanych przez klasę. Następnie iterujemy przez tę tablicę i wyświetlamy informacje o każdej metodzie.
Odbicie: Konstruktor
Możemy użyć klasy „Constructor” pakietu java.lang.reflect, aby sprawdzić i zmodyfikować konstruktory klasy Java.
W tym celu klasa konstruktora udostępnia następujące metody.
metoda | Opis |
---|---|
getConstructors () | Zwraca wszystkie konstruktory zadeklarowane w klasie i jej nadklasie. |
getDeclaredConstructor () | Zwraca wszystkie zadeklarowane konstruktory. |
getName () | Pobiera nazwę konstruktora. |
getModifiers () | Zwraca całkowitą reprezentację modyfikatora dostępu konstruktorów. |
getParameterCount () | Zwraca całkowitą liczbę parametrów dla konstruktorów. |
Poniższy przykład odbicia demonstruje odbicie konstruktorów klasy w Javie. Podobnie jak odbicie metody, tutaj również metoda getDeclaredConstructors zwraca tablicę konstruktorów dla klasy. Następnie przechodzimy przez tę tablicę konstruktorów, aby wyświetlić informacje o każdym konstruktorze.
import java.lang.Class; import java.lang.reflect.*; //declare a class Person with three constructors class Person { public Person() { } //constructor with no parameters public Person(String name) { } //constructor with 1 parameter private Person(String name, int age) {} //constructor with 2 parameters } class Main { public static void main(String() args) { try { Person person = new Person(); Class obj = person.getClass(); // get array of constructors in a class using getDeclaredConstructor() Constructor() constructors = obj.getDeclaredConstructors(); System.out.println('Constructors for Person Class:'); for(Constructor c : constructors) { // get names of constructors System.out.println('Constructor Name: ' + c.getName()); // get access modifier of constructors int modifier = c.getModifiers(); System.out.print ('Modifier: ' + Modifier.toString(modifier) + ' '); // get the number of parameters in constructors System.out.println('Parameters: ' + c.getParameterCount()); //if there are parameters, get parameter type of each parameter if(c.getParameterCount() > 0){ Class() paramList=c.getParameterTypes(); System.out.print ('Constructor parameter types :'); for (Class class1 : paramList) { System.out.print(class1.getName() +' '); } } System.out.println('
'); } } catch(Exception e) { e.printStackTrace(); } } }
Wynik
Wady refleksji
Odbicie jest potężne, ale nie powinno być używane bezkrytycznie. Jeśli możliwe jest działanie bez odbicia, lepiej go unikać.
Poniżej wymieniono kilka wad Refleksji:
- Narzut wydajności: Chociaż odbicie jest potężną funkcją, operacje odblaskowe nadal działają wolniej niż operacje nieodblaskowe. Dlatego powinniśmy unikać używania odbić w aplikacjach krytycznych dla wydajności.
- Ograniczenia bezpieczeństwa: Ponieważ odbicie jest funkcją środowiska wykonawczego, może wymagać uprawnień w czasie wykonywania. Tak więc w przypadku aplikacji, które wymagają wykonania kodu z ograniczonymi ustawieniami zabezpieczeń, odbicie może być bezużyteczne.
- Ekspozycja elementów wewnętrznych: Korzystając z odbicia, możemy uzyskać dostęp do prywatnych pól i metod w klasie. W ten sposób refleksja łamie abstrakcję, która może sprawić, że kod będzie nieporęczny i niefunkcjonalny.
Często Zadawane Pytania
P # 1) Dlaczego odbicie jest używane w Javie?
Odpowiedź: Korzystając z odbicia, możemy sprawdzać klasy, interfejsy, konstruktory, pola i metody w czasie wykonywania, nawet jeśli są anonimowe w czasie kompilacji. Ta inspekcja pozwala nam modyfikować zachowanie tych jednostek w czasie wykonywania.
Pytanie nr 2) Gdzie jest używane odbicie?
Odpowiedź: Odbicie jest używane do pisania frameworków, które współdziałają z klasami zdefiniowanymi przez użytkownika, w których programista nawet nie wie, jakie będą klasy lub inne jednostki.
Pytanie nr 3) Czy Java Reflection jest powolna?
Odpowiedź: Tak, jest wolniejszy niż kod bezodblaskowy.
Pytanie 4) Czy Java Reflection jest zła?
Odpowiedź: W pewnym sensie tak. Przede wszystkim tracimy bezpieczeństwo w czasie kompilacji. Bez bezpieczeństwa w czasie kompilacji możemy otrzymać błędy czasu wykonywania, które mogą mieć wpływ na użytkowników końcowych. Trudno będzie również zdebugować błąd.
Pytanie nr 5) Jak zatrzymać odbicie w Javie?
Odpowiedź: Po prostu unikamy używania refleksji, pisząc operacje bez odbicia. A może możemy użyć pewnych ogólnych mechanizmów, takich jak niestandardowa walidacja z refleksją.
Więcej informacji o Java Reflection
Pakiet java.lang.reflect zawiera klasy i interfejsy do wykonania refleksji. A java.lang.class może służyć jako punkt wejścia do refleksji.
Jak zdobyć obiekty klas:
1. Jeśli masz wystąpienie obiektu,
class c = obj.getclass ();
2. Jeśli znasz typ zajęć,
klasa c = type.getClass ();
3. Jeśli znasz nazwę klasy,
Class c = Class.forName („com.demo.Mydemoclass”);
Jak zdobyć członków klasy:
Członkami klasy są pola (zmienne klas) i metody.
- getFields () - Używane do pobierania wszystkich pól poza polami prywatnymi.
- getDeclaredField () - Używane do zdobywania prywatnych pól.
- getDeclaredFields () - Służy do zdobywania pól prywatnych i publicznych.
- getMethods () - Służy do pobierania wszystkich metod z wyjątkiem metod prywatnych.
- getDeclaredMethods () –Używane do metod publicznych i prywatnych.
Programy demonstracyjne:
ReflectionHelper.java:
Jest to klasa, w której będziemy sprawdzać za pomocą interfejsu API odbicia.
jak stworzyć plik makefile c ++
class ReflectionHelper { private int age; private String name; public String deptName; public int empID; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } }
ReflectionDemo.java
public class ReflectionDemo { public static void main(String() args) throws NoSuchFieldException, SecurityException { //get the class Class ReflectionHelperclass=ReflectionHelper.class; //get the name of the class String className = ReflectionHelperclass.getName(); System.out.println('className=='+className); System.out.println('getModifiers'+ReflectionHelperclass.getModifier s()); System.out.println('getSuperclass'+ReflectionHelperclass.getSupercla ss()); System.out.println('getPackage'+ReflectionHelperclass.getPackage()); Field() fields =ReflectionHelperclass.getFields(); //getting only the public fields for(Field oneField : fields) { Field field = ReflectionHelperclass.getField(oneField.getName()); String fieldname = field.getName(); System.out.println('only the public fieldnames:::::'+fieldname); } //getting all the fields of the class Field() privatefields =ReflectionHelperclass.getDeclaredFields(); for(Field onefield : privatefields) { Field field = ReflectionHelperclass.getDeclaredField(onefield.getName()); String fieldname = field.getName(); System.out.println('all the fieldnames in the class:::'+fieldname); } Method() methods =ReflectionHelperclass.getDeclaredMethods(); for(Method m: methods) { System.out.println('methods::::'+m.getName()); } }}
Wniosek
W tym samouczku szczegółowo wyjaśniono interfejs API Reflection w języku Java. Zobaczyliśmy, jak wykonać odbicie klas, interfejsów, pól, metod i konstruktorów, a także kilka wad refleksji.
Refleksja jest stosunkowo zaawansowaną funkcją w Javie, ale powinna być używana przez programistów, którzy mają silną pozycję w tym języku. Dzieje się tak, ponieważ może powodować nieoczekiwane błędy i wyniki, jeśli nie jest używany ostrożnie.
Chociaż odbicie jest potężne, należy z niego korzystać ostrożnie. Niemniej jednak, korzystając z refleksji, możemy tworzyć aplikacje, które nie są świadome istnienia klas i innych jednostek do czasu uruchomienia.
=> Zapoznaj się z podręcznikiem Java dla początkujących tutaj.
rekomendowane lektury
- Samouczek klasy skanera Java z przykładami
- Klasa Java Integer i Java BigInteger z przykładami
- Samouczek JAVA dla początkujących: ponad 100 praktycznych samouczków wideo Java
- Wprowadzenie do języka programowania Java - samouczek wideo
- Co to jest wektor Java | Samouczek klasy wektorowej Java z przykładami
- Interfejs Java i samouczek klasy abstrakcyjnej z przykładami
- Metoda substring () Java - samouczek z przykładami
- Samouczek Java Collections Framework (JCF)