java reflection tutorial with examples
Aquest tutorial de vídeo explica què és Reflection i com implementar-lo mitjançant l'API Reflection:
La reflexió a Java consisteix a inspeccionar i canviar el comportament d’un programa en temps d’execució.
Amb l'ajuda d'aquesta API de reflexió, podeu inspeccionar classes, constructors, modificadors, camps, mètodes i interfícies en temps d'execució. Per exemple, podeu obtenir el nom de la classe o obtenir informació sobre els membres privats de la classe.
Llegiu tota la informació Sèrie d'entrenament JAVA per obtenir més informació sobre els conceptes de Java.
Aquí teniu un vídeo tutorial sobre la reflexió de Java:
Què aprendreu:
Reflexió a Java
Som conscients que en una classe determinada podem modificar les seves propietats i mètodes en el moment de la compilació i és molt fàcil fer-ho. Tant si les propietats com els mètodes són anònims o tenen noms, es poden canviar segons vulguem durant la compilació.
Però no podem canviar aquestes classes, mètodes o camps en temps d'execució sobre la marxa. En altres paraules, és molt difícil canviar el comportament de diversos components de programació en temps d'execució, especialment per a objectes desconeguts.
El llenguatge de programació Java proporciona una característica anomenada 'Reflexió' que ens permet modificar el comportament en temps d'execució d'una classe o camp o mètode en temps d'execució.
Així, una reflexió es pot definir com a “Tècnica per inspeccionar i modificar el comportament en temps d'execució d'un objecte desconegut en temps d'execució. Un objecte pot ser una classe, un camp o un mètode '.
Reflection és una 'interfície de programació d'aplicacions' (API) proporcionada per Java.
A continuació es mostra el procés de 'reflexió'.
A la representació anterior, podem veure que tenim un objecte desconegut. A continuació, fem servir l'API Reflection en aquest objecte. Com a resultat, podem modificar el comportament d’aquest objecte en temps d’execució.
Per tant, podem utilitzar l’API Reflection als nostres programes amb el propòsit de modificar el comportament de l’objecte. Els objectes poden ser com ara mètodes, interfícies, classes, etc. Inspeccionem aquests objectes i després canviem el seu comportament en temps d'execució mitjançant l'API de reflexió.
A Java, el “java.lang” i el “java.lang.reflect” són els dos paquets que proporcionen classes per a la reflexió. La classe especial 'java.lang.Class' proporciona els mètodes i les propietats per extreure metadades mitjançant les quals podem inspeccionar i modificar el comportament de la classe.
Utilitzem l'API Reflection proporcionada pels paquets anteriors per modificar la classe i els seus membres, inclosos els camps, mètodes, constructors, etc. en temps d'execució. Una característica distintiva de l'API Reflection és que també podem manipular els membres de dades privades o els mètodes de la classe.
L'API Reflection s'utilitza principalment en:
- La reflexió s'utilitza principalment en eines de depuració, JUnit i marcs per inspeccionar i canviar el comportament en temps d'execució.
- IDE (entorn de desenvolupament integrat) Per exemple. Eclipse IDE, NetBeans, etc.
- Eines de prova, etc.
- S'utilitza quan l'aplicació té biblioteques de tercers i quan voleu conèixer les classes i els mètodes disponibles.
API de reflexió a Java
Mitjançant l'API Reflection, podem implementar la reflexió sobre les entitats següents:
- Camp : La classe Field conté informació que fem servir per declarar una variable o un camp com un tipus de dades (int, double, String, etc.), modificador d’accés (privat, públic, protegit, etc.), nom (identificador) i valor.
- Mètode : La classe Method ens pot ajudar a extreure informació com el modificador d’accés del mètode, el tipus de retorn del mètode, el nom del mètode, els tipus de paràmetres del mètode i els tipus d’excepció generats pel mètode.
- constructor : La classe constructor proporciona informació sobre el constructor de classes que inclou modificadors d'accés al constructor, nom del constructor i tipus de paràmetres.
- Edita : La classe Modifier ens proporciona informació sobre un modificador d'accés específic.
Totes les classes anteriors formen part del paquet java.lang.reflect. A continuació, discutirem cadascuna d’aquestes classes i utilitzarem exemples de programació per demostrar la reflexió sobre aquestes classes.
Comencem primer per la classe java.lang.Class.
java.lang.Class Class
La classe java.lang.The conté tota la informació i dades sobre classes i objectes en temps d'execució. Aquesta és la classe principal que s’utilitza per a la reflexió.
La classe java.lang.Class proporciona:
- Mètodes per recuperar metadades de classe en temps d'execució.
- Mètodes per inspeccionar i modificar el comportament d'una classe en temps d'execució.
Creeu objectes java.lang.Class
Podem crear objectes de java.lang.Class mitjançant una de les opcions següents.
què és un arbre de decisions en la mineria de dades
# 1) .extensió de classe
La primera opció per crear un objecte de classe és utilitzar l'extensió .class.
Per exemple,si Test és una classe, podem crear un objecte Class de la següent manera:
Class obj_test = Test.class;
A continuació, podem utilitzar l'obj_test per fer reflexions, ja que aquest objecte tindrà tota la informació sobre la classe Test.
# 2) mètode forName ()
El mètode forName () pren el nom de la classe com a argument i retorna l'objecte Class.
Per exemple,es pot crear l'objecte de la classe Test de la següent manera:
class obj_test = Class.forName (“Test”);
# 3) mètode getClas ()
El mètode getClass () utilitza l'objecte d'una classe per obtenir l'objecte java.lang.Class.
Per exemple,tingueu en compte la següent peça de codi:
Test obj = new Test (); Class obj_test = obj.getClass ();
A la primera línia, vam crear un objecte de classe de prova. Després, utilitzant aquest objecte, vam anomenar el mètode 'getClass ()' per obtenir un objecte object_test de java.lang.Class.
Obteniu modificadors d’accés i classe super
java.lang.class proporciona un mètode 'getSuperClass ()' que s'utilitza per obtenir la superclasse de qualsevol classe.
De la mateixa manera, proporciona un mètode getModifier () que retorna el modificador d'accés de la classe.
L'exemple següent mostra el mètode 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(); } } }
Sortida
A l'exemple de programació anterior, es defineix una interfície Person amb un mètode solitari 'display ()'. A continuació, definim una classe Student que implementa la interfície de persona. Al mètode principal, fem servir el mètode getClass () per recuperar l'objecte Class i, a continuació, accedir al pare o a la superclasse de l'objecte Student mitjançant el mètode getSuperClass ().
Obteniu interfícies
Si la classe implementa algunes interfícies, podem obtenir aquests noms d’interfícies mitjançant el mètode getInterfaces () del java.lang.Class. Per a això, hem de fer una reflexió sobre la classe Java.
L'exemple de programació següent mostra l'ús del mètode getInterfaces () a 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(); } } }
Sortida
Al programa anterior, hem definit dues interfícies, és a dir, Animals i PetAnimals. A continuació, definim una classe Dog, que implementa aquestes dues interfícies.
En el mètode principal, recuperem l’objecte de la classe Dog a java.lang.Class per realitzar la reflexió. A continuació, fem servir el mètode getInterfaces () per recuperar les interfícies implementades per la classe Dog.
Reflexió: obteniu valor de camp
Com ja s'ha esmentat, el paquet java.lang.reflect proporciona la classe Field que ens ajuda a reflectir el camp o les dades de la classe.
A continuació es detallen els mètodes proporcionats per la classe Field per a la reflexió d’un camp.
Mètode | Descripció |
---|---|
getField ('fieldName') | Retorna el camp (públic) amb un nom de camp especificat. |
getFields () | Retorna tots els camps públics (tant per a classe com per a superclasse). |
getDeclaredFields () | Recupera tots els camps de la classe. |
getModifier () | Retorna la representació sencera del modificador d'accés del camp. |
set (classObject, valor) | Assigna el valor especificat al camp. |
obtenir (classObject) | Recupera el valor del camp. |
setAccessible (booleà) | Feu accessible el camp privat passant per cert. |
getDeclaredField ('fieldName') | Retorna el camp amb un nom especificat. |
A continuació es presenten dos exemples de reflexió que demostren la reflexió sobre l’àmbit públic i privat.
El programa Java següent mostra la reflexió sobre un camp públic.
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(); } } }
Sortida
En aquest programa, hem declarat una classe 'Estudiant' que té un camp públic StudentName. A continuació, utilitzant la interfície API de la classe Field, fem una reflexió sobre el camp StudentName i recuperem el seu modificador d’accés i el seu valor.
El següent programa realitza reflexions sobre un camp privat de la classe. Les operacions són similars excepte que hi ha una trucada de funció addicional feta per al camp privat. Hem de trucar a setAccessible (true) per al camp privat. Després realitzem la reflexió sobre aquest camp de manera similar a la pública.
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(); } } }
Sortida
Reflexió: mètode
De manera similar als camps de la classe, també podem fer reflexions sobre els mètodes de classe i modificar el seu comportament en temps d'execució. Per a això, fem servir la classe Method del paquet java.lang.reflect.
A continuació es detallen les funcions proporcionades per la classe Method per a la reflexió del mètode de la classe.
Mètode | Descripció |
---|---|
getMethods () | Recupera tots els mètodes públics definits a la classe i a la seva superclasse. |
getDeclaredMethod () | Retorna els mètodes declarats a la classe. |
getName () | Retorna els noms dels mètodes. |
getModifiers () | Retorna la representació sencera del modificador d'accés del mètode. |
getReturnType () | Retorna el tipus de retorn del mètode. |
L'exemple següent mostra la reflexió dels mètodes de classe a Java mitjançant les API anteriors.
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(); } } }
Sortida
Al programa anterior, veiem que el mètode getDeclaredMethods retorna la matriu de mètodes declarats per la classe. A continuació, recorrem aquesta matriu i mostrem la informació de cada mètode.
Reflexió: constructor
Podem utilitzar la classe 'Constructor' del paquet java.lang.reflect per inspeccionar i modificar els constructors d'una classe Java.
La classe constructor proporciona els mètodes següents per a aquest propòsit.
Mètode | Descripció |
---|---|
getConstructors () | Retorna tots els constructors declarats a la classe i la seva superclasse. |
getDeclaredConstructor () | Retorna tots els constructors declarats. |
getName () | Recupera el nom del constructor. |
getModifiers () | Retorna la representació sencera del modificador d'accés dels constructors. |
getParameterCount () | Retorna el nombre total de paràmetres per a un constructor. |
L'exemple de reflexió següent mostra la reflexió dels constructors d'una classe a Java. Igual que la reflexió del mètode, aquí també el mètode getDeclaredConstructors retorna una matriu de constructors per a una classe. A continuació, recorrem aquesta matriu de constructors per mostrar informació sobre cada constructor.
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(); } } }
Sortida
Inconvenients de la reflexió
La reflexió és poderosa, però no s’ha d’utilitzar indistintament. Si és possible operar sense utilitzar la reflexió, és preferible evitar-ne l’ús.
A continuació es detallen alguns inconvenients de la reflexió:
- Rendiment general: Tot i que la reflexió és una característica poderosa, les operacions reflectants encara tenen un rendiment més lent que les operacions no reflectants. Per tant, hauríem d’evitar l’ús de reflexions en aplicacions de rendiment crític.
- Restriccions de seguretat: Com que la reflexió és una característica d’execució, és possible que requereixin permisos en temps d’execució. Per tant, per a les aplicacions que requereixen que el codi s’executi en una configuració de seguretat restringida, és possible que la reflexió no serveixi de res.
- Exposició d’internes: Mitjançant l’ús de la reflexió, podem accedir a camps i mètodes privats d’una classe. Així, la reflexió trenca l’abstracció que pot fer que el codi sigui inaportable i disfuncional.
Preguntes freqüents
P # 1) Per què s'utilitza la reflexió a Java?
Resposta: Mitjançant la reflexió podem inspeccionar classes, interfícies, constructors, camps i mètodes en temps d'execució, encara que siguin anònims en el moment de la compilació. Aquesta inspecció ens permet modificar el comportament d’aquestes entitats en temps d’execució.
Q # 2) On s’utilitza la reflexió?
Resposta: La reflexió s’utilitza en marcs d’escriptura que interoperen amb classes definides per l’usuari, en què el programador ni tan sols sap quines seran les classes o altres entitats.
Q # 3) Java Reflection és lent?
Resposta: Sí, és més lent que el codi de no reflexió.
Q # 4) Java Reflection és dolent?
Resposta: En certa manera, sí. En primer lloc, perdem la seguretat en temps de compilació. Sense seguretat en temps de compilació, és possible que obtinguem errors en temps d'execució que puguin afectar els usuaris finals. També serà difícil depurar l’error.
Q # 5) Com atureu una reflexió a Java?
Resposta: Simplement evitem utilitzar la reflexió escrivint operacions que no siguin reflexions. O potser podem utilitzar alguns mecanismes genèrics com una validació personalitzada amb reflexió.
Més informació sobre Java Reflection
El paquet java.lang.reflect té les classes i les interfícies per fer reflexions. I java.lang.class es pot utilitzar com a punt d’entrada per a la reflexió.
Com obtenir els objectes de la classe:
1. Si teniu instància d’un objecte,
classe c = obj.getclass ();
2. Si coneixeu el tipus de classe,
classe c = type.getClass ();
3. Si coneixeu el nom de la classe,
Classe c = Class.forName ('com.demo.Mydemoclass');
Com aconseguir els membres de la classe:
Els membres de la classe són camps (variables de classe) i mètodes.
- getFields () - S'utilitza per obtenir tots els camps excepte els camps privats.
- getDeclaredField () - S'utilitza per obtenir els camps privats.
- getDeclaredFields () - S'utilitza per obtenir els camps públics i privats.
- getMethods () - S'utilitza per obtenir tots els mètodes excepte els mètodes privats.
- getDeclaredMethods () –S’utilitza per obtenir mètodes públics i privats.
Programes de demostració:
ReflectionHelper.java:
Aquesta és la classe on inspeccionarem mitjançant l'API de reflexió.
preguntes i respostes de l'entrevista de Linux per a usuaris experimentats
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()); } }}
Conclusió
Aquest tutorial explica detalladament l'API Reflection a Java. Vam veure com realitzar la reflexió de classes, interfícies, camps, mètodes i constructors juntament amb alguns inconvenients de la reflexió.
La reflexió és una característica relativament avançada a Java, però hauria de ser utilitzada pels programadors que tinguessin una fortalesa en el llenguatge. Això es deu al fet que pot provocar errors i resultats inesperats si no s’utilitza amb precaució.
Tot i que la reflexió és potent, s’ha d’utilitzar amb cura. Tot i això, mitjançant la reflexió podem desenvolupar aplicacions que desconeixin les classes i altres entitats fins a l'execució.
=> Feu una ullada a la guia per a principiants de Java aquí
Lectura recomanada
- Tutorial de classe de Java Scanner amb exemples
- Java Integer i Java BigInteger Class amb exemples
- Tutorial JAVA per a principiants: més de 100 tutorials pràctics de vídeo Java
- Introducció al llenguatge de programació Java: vídeo tutorial
- Què és Java Vector | Tutorial de Java Vector Class amb exemples
- Interfície Java i tutoria de classes abstractes amb exemples
- Mètode Java substring (): tutorial amb exemples
- Tutorial sobre Java Collections Framework (JCF)