java reflection tutorial with examples
Този урок за видео обяснява какво е Reflection и как да го приложите с помощта на Reflection API:
Отражението в Java е да се провери и промени поведението на програма по време на изпълнение.
С помощта на този API за отражение можете да проверявате класове, конструктори, модификатори, полета, методи и интерфейси по време на изпълнение. Например, можете да получите името на класа или можете да получите подробности за частните членове на класа.
Прочетете цялата ни Серия за обучение на JAVA за повече представа за концепциите на Java.
Ето видео урок за Java Reflection:
Какво ще научите:
Отражение в Java
Наясно сме, че в даден клас можем да модифицираме неговите свойства и методи по време на компилация и е много лесно да го направим. Независимо дали свойствата и методите са анонимни или имат имена, те могат да бъдат променени по наше желание по време на компилация.
Но не можем да променим тези класове или методи или полета по време на изпълнение в движение. С други думи, много е трудно да се промени поведението на различни програмни компоненти по време на изпълнение, особено за неизвестни обекти.
Java езикът за програмиране предоставя функция, наречена „Отражение“ което ни позволява да модифицираме поведението по време на изпълнение на клас или поле или метод по време на изпълнение.
По този начин Отражение може да се определи като a „Техника за проверка и модифициране на поведението по време на изпълнение на неизвестен обект по време на изпълнение. Обектът може да бъде клас, поле или метод. '
Reflection е „Приложен програмен интерфейс“ (API), предоставен от Java.
Процесът „Отражение“ е изобразен по-долу.
В горното представяне можем да видим, че имаме неизвестен обект. След това използваме API за отразяване на този обект. В резултат на това можем да модифицираме поведението на този обект по време на изпълнение.
По този начин можем да използваме API за отразяване в нашите програми с цел промяна на поведението на обекта. Обектите могат да бъдат нещо като методи, интерфейси, класове и др. Ние проверяваме тези обекти и след това променяме поведението им по време на изпълнение с помощта на API за отражение.
В Java „java.lang“ и „java.lang.reflect“ са двата пакета, които осигуряват класове за размисъл. Специалният клас “java.lang.Class” предоставя методите и свойствата за извличане на метаданни, с помощта на които можем да проверяваме и модифицираме поведението на класа.
Ние използваме Reflection API, предоставен от горните пакети, за да модифицираме класа и неговите членове, включително полета, методи, конструктори и др. По време на изпълнение. Отличителна черта на Reflection API е, че можем също да манипулираме членовете на частните данни или методите на класа.
API за отражение се използва главно в:
- Отражението се използва главно в инструменти за отстраняване на грешки, JUnit и рамки за проверка и промяна на поведението по време на изпълнение.
- IDE (интегрирана среда за развитие) E.g. Eclipse IDE, NetBeans и др.
- Тестови инструменти и т.н.
- Използва се, когато вашето приложение има библиотеки на трети страни и когато искате да знаете за наличните класове и методи.
API за отразяване в Java
Използвайки Reflection API, можем да реализираме отражението върху следните обекти:
- Поле : Класът Field има информация, която използваме, за да декларираме променлива или поле като тип данни (int, double, String и др.), Модификатор на достъп (частен, публичен, защитен и т.н.), име (идентификатор) и стойност.
- Метод : Класът на метода може да ни помогне да извлечем информация като модификатор на достъп на метода, тип на връщане на метода, име на метод, типове параметри на метода и типове изключения, повдигнати от метода.
- Строител : Класът на конструктора дава информация за конструктора на клас, който включва модификатор за достъп до конструктор, име на конструктор и типове параметри.
- редактиране : Класът модификатор ни дава информация за конкретен модификатор на достъп.
Всички горепосочени класове са част от пакета java.lang.reflect. След това ще обсъдим всеки от тези класове и ще използваме примери за програмиране, за да демонстрираме отражението върху тези класове.
Нека първо започнем с класа java.lang.Class.
java.lang.Класов клас
Класът java.lang.Класът съхранява цялата информация и данни за класове и обекти по време на изпълнение. Това е основният клас, използван за размисъл.
Класът java.lang.Class осигурява:
- Методи за извличане на метаданни на класа по време на изпълнение.
- Методи за проверка и модифициране на поведението на клас по време на изпълнение.
Създайте обекти java.lang.Class
Можем да създадем обекти на java.lang.Class, като използваме една от следните опции.
как да отворя swf файл на хром
# 1) .класно разширение
Първата опция за създаване на обект на Class е чрез използване на разширението .class.
Например,ако Test е клас, тогава можем да създадем обект Class, както следва:
Class obj_test = Test.class;
След това можем да използваме obj_test, за да извършим отражение, тъй като този обект ще има цялата информация за класа Test.
# 2) метод forName ()
Методът forName () приема името на класа като аргумент и връща обекта Class.
Например,обектът на класа Test може да бъде създаден, както следва:
class obj_test = Class.forName (“Test”);
# 3) метод getClas ()
методът getClass () използва обект от клас, за да получи обекта java.lang.Class.
Например,помислете за следния код:
Test obj = new Test (); Class obj_test = obj.getClass ();
В първия ред създадохме обект от клас Test. След това използвайки този обект, ние извикахме метода “getClass ()”, за да получим обект obj_test на java.lang.Class.
Вземете модификатори за супер клас и достъп
java.lang.class предоставя метод “getSuperClass ()”, който се използва за получаване на суперклас от всеки клас.
По същия начин той предоставя метод getModifier (), който връща модификатора за достъп на класа.
Примерът по-долу демонстрира метода 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(); } } }
Изход
В горния пример за програмиране интерфейсът Person се дефинира с метод на самот ‘display ()’. След това дефинираме студентски клас, изпълняващ интерфейса на човека. В основния метод използваме метода getClass (), за да извлечем обекта Class и след това да осъществим достъп до родителския или суперклас на обекта Student, използвайки метода getSuperClass ().
Вземете интерфейси
Ако класът реализира някои интерфейси, тогава можем да получим имената на тези интерфейси, използвайки метода getInterfaces () на java.lang.Class. За това трябва да извършим размисъл върху класа Java.
Примерът по-долу за програмиране изобразява използването на метода getInterfaces () в 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(); } } }
Изход
В горната програма дефинирахме два интерфейса, т.е. Animals и PetAnimals. След това дефинираме клас Dog, който реализира и двата интерфейса.
В основния метод извличаме обекта от клас Dog в java.lang.Class, за да извършим отражение. След това използваме метода getInterfaces (), за да извлечем интерфейсите, които са внедрени от класа Dog.
Отражение: Вземете стойност на полето
Както вече споменахме, пакетът java.lang.reflect предоставя клас Field, който ни помага да отразяваме полето или членовете на данните в класа.
По-долу са изброени методите, предоставени от клас Field за отражение на поле.
Метод | Описание |
---|---|
getField ('fieldName') | Връща полето (публично) с посочено име на поле. |
getFields () | Връща всички публични полета (както за клас, така и за суперклас). |
getDeclaredFields () | Извлича всички полета на класа. |
getModifier () | Връща цяло число представяне на модификатора за достъп на полето. |
набор (classObject, стойност) | Присвоява посочената стойност на полето. |
get (classObject) | Извлича стойност на полето. |
setAccessible (булева стойност) | Направете частното поле достъпно, като предадете true. |
getDeclaredField ('fieldName') | Връща полето с посочено име. |
По-долу са дадени два примера за размисъл, които демонстрират отражението върху публичното и частното поле.
Програмата Java по-долу демонстрира отражението върху публично поле.
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(); } } }
Изход
В тази програма декларирахме клас „Студент“ с публично поле StudentName. След това, използвайки API интерфейса на клас Field, извършваме отражение на полето StudentName и извличаме модификатора и стойността на неговия достъп.
Следващата програма извършва размисъл върху частно поле на класа. Операциите са подобни, с изключение на това, че има едно допълнително извикване на функция за частното поле. Трябва да извикаме setAccessible (true) за частното поле. След това извършваме размисъл върху това поле по подобен начин като публичното поле.
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(); } } }
Изход
Отражение: Метод
Подобно на полетата на класа, ние също можем да извършим размисъл върху методите на класа и да модифицираме тяхното поведение по време на изпълнение. За това използваме метода клас на пакета java.lang.reflect.
По-долу са изброени функциите, предоставени от метода клас за Отражение на метода на класа.
Метод | Описание |
---|---|
getMethods () | Извлича всички публични методи, дефинирани в класа и неговия суперклас. |
getDeclaredMethod () | Връща методи, декларирани в класа. |
getName () | Връща имената на методите. |
getModifiers () | Връща цяло число представяне на модификатора за достъп на метода. |
getReturnType () | Връща типа на връщане на метода. |
Примерът по-долу показва отражението на методите на класа в Java, използвайки горните 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(); } } }
Изход
В горната програма виждаме, че методът getDeclaredMethods връща масива от методи, декларирани от класа. След това итерираме през този масив и показваме информацията за всеки метод.
Отражение: Конструктор
Можем да използваме класа „Конструктор“ на пакета java.lang.reflect, за да инспектираме и модифицираме конструкторите на Java клас.
Класът конструктор предоставя следните методи за тази цел.
Метод | Описание |
---|---|
getConstructors () | Връща всички конструктори, декларирани в клас и неговия суперклас. |
getDeclaredConstructor () | Връща всички декларирани конструктори. |
getName () | Извлича името на конструктора. |
getModifiers () | Връща цялостното представяне на модификатора на достъпа на конструктори. |
getParameterCount () | Връща общия брой параметри за конструктори. |
Примерът за отражение по-долу демонстрира отражението на конструктори на клас в Java. Подобно на отражението на метода, тук също методът getDeclaredConstructors връща масив от конструктори за клас. След това преминаваме през този масив на конструктор, за да покажем информация за всеки конструктор.
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(); } } }
Изход
Недостатъци на отражението
Отражението е мощно, но не бива да се използва безразборно. Ако е възможно да се работи без използване на отражение, за предпочитане е да се избягва използването му.
По-долу са изброени няколко недостатъка на Reflection:
- Натоварване на производителността: Въпреки че отражението е мощна функция, отразяващите операции все още имат по-ниска производителност от неотразяващите операции. Следователно трябва да избягваме използването на отражения в критични за изпълнението приложения.
- Ограничения за сигурност: Тъй като отражението е функция за изпълнение, може да се наложи разрешения за изпълнение. Така че за приложенията, които изискват кодът да се изпълнява в ограничена настройка за сигурност, тогава отражението може да не е от полза.
- Излагане на вътрешни елементи: Използвайки отражение, можем да получим достъп до частни полета и методи в клас. По този начин размисълът прекъсва абстракцията, която може да направи кода непоносим и нефункционален.
често задавани въпроси
В # 1) Защо Reflection се използва в Java?
Отговор: Използвайки отражение, можем да проверяваме класове, интерфейси, конструктори, полета и методи по време на изпълнение, дори ако те са анонимни по време на компилация. Тази проверка ни позволява да модифицираме поведението на тези обекти по време на изпълнение.
Q # 2) Къде се използва Reflection?
Отговор: Отражението се използва при писане на рамки, които си взаимодействат с дефинирани от потребителя класове, при което програмистът дори не знае какви ще бъдат класовете или други обекти.
Q # 3) Бавно ли е отражението на Java?
Отговор: Да, той е по-бавен от кода без отражение.
Q # 4) Лошо ли е отражението на Java?
Отговор: В известен смисъл да. На първо място, губим безопасността по време на компилация. Без безопасност по време на компилация може да получим грешки при изпълнението, които могат да засегнат крайните потребители. Също така ще бъде трудно да отстраните грешката.
Q # 5) Как да спрете Отражение в Java?
Отговор: Ние просто избягваме да използваме размисъл, като пишем операции без отразяване. Или може би можем да използваме някои общи механизми като персонализирана проверка с отражение.
Повече за Java Reflection
java.lang.reflect пакетът има класове и интерфейси, за да направи отражение. А java.lang.class може да се използва като входна точка за отражението.
Как да получите обектите на класа:
1. Ако имате екземпляр на обект,
клас c = obj.getclass ();
2. Ако знаете типа на класа,
клас c = type.getClass ();
3. Ако знаете името на класа,
Клас c = Class.forName (“com.demo.Mydemoclass”);
Как да получите членовете на класа:
Членовете на класа са полета (променливи на класа) и методи.
- getFields () - Използва се за получаване на всички полета с изключение на частните полета.
- getDeclaredField () - Използва се за получаване на частни полета.
- getDeclaredFields () - Използва се за получаване на частно и публично поле.
- getMethods () - Използва се за получаване на всички методи с изключение на частните методи.
- getDeclaredMethods () –Използва се за получаване на публични и частни методи.
Демо програми:
ReflectionHelper.java:
Това е класът, в който ще проверяваме с помощта на API за отражение.
какво прави double в java
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()); } }}
Заключение
Този урок обясни подробно API за отразяване в Java. Видяхме как да извършим отражение на класове, интерфейси, полета, методи и конструктори, заедно с няколко недостатъка на отражението.
Reflection е относително усъвършенствана функция в Java, но трябва да се използва от програмисти, които имат крепост в езика. Това е така, защото може да причини неочаквани грешки и резултати, ако не се използва внимателно.
Въпреки че отражението е мощно, то трябва да се използва внимателно. Въпреки това, използвайки отражение, можем да разработим приложения, които не са наясно с класове и други обекти до времето на изпълнение.
=> Погледнете тук ръководството за начинаещи Java.
Препоръчително четене
- Урок за клас Java Scanner с примери
- Java Integer и Java BigInteger клас с примери
- Урок за JAVA за начинаещи: 100+ практически ръководства за Java видео
- Въведение в езика за програмиране на Java - видео урок
- Какво е Java Vector | Урок за Java Vector Class с примери
- Урок за интерфейс на Java и абстрактен клас с примери
- Метод на Java substring () - Урок с примери
- Урок за Java Collections Framework (JCF)