java reflection tutorial with examples
Questo tutorial video spiega cos'è Reflection e come implementarlo utilizzando l'API Reflection:
La riflessione in Java consiste nell'ispezionare e modificare il comportamento di un programma in fase di esecuzione.
Con l'aiuto di questa API di riflessione, puoi ispezionare classi, costruttori, modificatori, campi, metodi e interfacce in fase di esecuzione. Per esempio, puoi ottenere il nome della classe o puoi ottenere i dettagli dei membri privati della classe.
Leggi tutto il nostro Serie di formazione JAVA per maggiori informazioni sui concetti Java.
Ecco un video tutorial su Java Reflection:
Cosa imparerai:
- Riflessione in Java
- API di riflessione in Java
- java.lang.Class Classe
- Crea oggetti java.lang.Class
- Ottieni modificatori di super classe e accesso
- Ottieni interfacce
- Riflessione: ottieni valore campo
- Riflessione: metodo
- Riflessione: costruttore
- Inconvenienti della riflessione
- Domande frequenti
- Ulteriori informazioni su Java Reflection
- Conclusione
Riflessione in Java
Siamo consapevoli che in una data classe possiamo modificare le sue proprietà e metodi in fase di compilazione ed è molto facile farlo. Sia che le proprietà ei metodi siano anonimi o abbiano nomi, possono essere modificati a nostro piacimento durante la compilazione.
Ma non possiamo cambiare queste classi, metodi o campi in fase di esecuzione al volo. In altre parole, è molto difficile modificare il comportamento di vari componenti di programmazione in fase di esecuzione, specialmente per oggetti sconosciuti.
Il linguaggio di programmazione Java fornisce una funzionalità chiamata 'Riflessione' che ci consente di modificare il comportamento di runtime di una classe o di un campo o di un metodo in fase di runtime.
Quindi una riflessione può essere definita come un “Tecnica di ispezione e modifica del comportamento di runtime di un oggetto sconosciuto in fase di esecuzione. Un oggetto può essere una classe, un campo o un metodo. '
Reflection è una 'Application Programming Interface' (API) fornita da Java.
Il processo di 'riflessione' è illustrato di seguito.
Nella rappresentazione sopra, possiamo vedere che abbiamo un oggetto sconosciuto. Quindi usiamo l'API di riflessione su questo oggetto. Di conseguenza, possiamo modificare il comportamento di questo oggetto in fase di esecuzione.
In questo modo possiamo utilizzare l'API di riflessione nei nostri programmi allo scopo di modificare il comportamento dell'oggetto. Gli oggetti possono essere qualsiasi cosa come metodi, interfacce, classi, ecc. Ispezioniamo questi oggetti e quindi ne modifichiamo il comportamento in fase di esecuzione utilizzando l'API di riflessione.
In Java, 'java.lang' e 'java.lang.reflect' sono i due pacchetti che forniscono classi per la riflessione. La classe speciale 'java.lang.Class' fornisce i metodi e le proprietà per estrarre i metadati utilizzando i quali possiamo ispezionare e modificare il comportamento della classe.
Usiamo la Reflection API fornita dai pacchetti precedenti per modificare la classe ei suoi membri inclusi campi, metodi, costruttori, ecc. In fase di esecuzione. Una caratteristica distintiva dell'API di Reflection è che possiamo anche manipolare i membri dei dati privati oi metodi della classe.
L'API Reflection viene utilizzata principalmente in:
- La riflessione viene utilizzata principalmente negli strumenti di debug, in JUnit e nei framework per ispezionare e modificare il comportamento in fase di esecuzione.
- IDE (Integrated Development Environment) Per esempio. Eclipse IDE, NetBeans, ecc.
- Strumenti di test ecc.
- Viene utilizzato quando l'applicazione dispone di librerie di terze parti e quando si desidera conoscere le classi e i metodi disponibili.
API di riflessione in Java
Utilizzando l'API Reflection, possiamo implementare la riflessione sulle seguenti entità:
- Campo : La classe Field contiene informazioni che utilizziamo per dichiarare una variabile o un campo come un tipo di dati (int, double, String, ecc.), Modificatore di accesso (privato, pubblico, protetto, ecc.), Nome (identificatore) e valore.
- Metodo : La classe Method può aiutarci a estrarre informazioni come il modificatore di accesso del metodo, il tipo restituito dal metodo, il nome del metodo, i tipi di parametro del metodo e i tipi di eccezione sollevati dal metodo.
- Costruttore : La classe Constructor fornisce informazioni sul costruttore della classe che include il modificatore di accesso del costruttore, il nome del costruttore e i tipi di parametro.
- modificare : La classe Modifier ci fornisce informazioni su uno specifico modificatore di accesso.
Tutte le classi precedenti fanno parte del pacchetto java.lang.reflect. Successivamente, discuteremo ciascuna di queste classi e utilizzeremo esempi di programmazione per dimostrare la riflessione su queste classi.
Iniziamo prima con la classe java.lang.Class.
java.lang.Class Classe
La classe java.lang.The contiene tutte le informazioni e i dati su classi e oggetti in fase di esecuzione. Questa è la classe principale utilizzata per la riflessione.
La classe java.lang.Class fornisce:
- Metodi per recuperare i metadati della classe in fase di esecuzione.
- Metodi per controllare e modificare il comportamento di una classe in fase di esecuzione.
Crea oggetti java.lang.Class
Possiamo creare oggetti di java.lang.Class usando una delle seguenti opzioni.
SQL Server 2012 intervista domande e risposte per esperti
# 1) estensione .class
La prima opzione per creare un oggetto di Class è usare l'estensione .class.
Per esempio,se Test è una classe, allora possiamo creare un oggetto Class come segue:
Class obj_test = Test.class;
Quindi possiamo usare obj_test per eseguire la riflessione poiché questo oggetto avrà tutte le informazioni sulla classe Test.
# 2) metodo forName ()
Il metodo forName () prende il nome della classe come argomento e restituisce l'oggetto Class.
Per esempio,l'oggetto della classe Test può essere creato come segue:
class obj_test = Class.forName (“Test”);
# 3) metodo getClas ()
Il metodo getClass () utilizza l'oggetto di una classe per ottenere l'oggetto java.lang.Class.
Per esempio,considera il seguente pezzo di codice:
Test obj = new Test (); Class obj_test = obj.getClass ();
Nella prima riga, abbiamo creato un oggetto della classe Test. Quindi utilizzando questo oggetto abbiamo chiamato il metodo 'getClass ()' per ottenere un oggetto obj_test di java.lang.Class.
Ottieni modificatori di super classe e accesso
java.lang.class fornisce un metodo 'getSuperClass ()' che viene utilizzato per ottenere la superclasse di qualsiasi classe.
Allo stesso modo, fornisce un metodo getModifier () che restituisce il modificatore di accesso della classe.
L'esempio seguente mostra il metodo 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(); } } }
Produzione
Nell'esempio di programmazione precedente, un'interfaccia Person è definita con un metodo solitario 'display ()'. Quindi definiamo una classe Student che implementa l'interfaccia della persona. Nel metodo principale, utilizziamo il metodo getClass () per recuperare l'oggetto Class e quindi accedere al genitore o alla superclasse dell'oggetto Student utilizzando il metodo getSuperClass ().
Ottieni interfacce
Se la classe implementa alcune interfacce, è possibile ottenere i nomi di queste interfacce utilizzando il metodo getInterfaces () di java.lang.Class. Per questo, dobbiamo eseguire una riflessione sulla classe Java.
L'esempio di programmazione riportato di seguito descrive l'uso del metodo getInterfaces () in 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(); } } }
Produzione
Nel programma sopra, abbiamo definito due interfacce, ovvero Animals e PetAnimals. Quindi definiamo una classe Dog, che implementa entrambe queste interfacce.
Nel metodo principale, recuperiamo l'oggetto della classe Dog in java.lang.Class per eseguire la riflessione. Quindi utilizziamo il metodo getInterfaces () per recuperare le interfacce implementate dalla classe Dog.
Riflessione: ottieni valore campo
Come già accennato, il pacchetto java.lang.reflect fornisce la classe Field che ci aiuta a riflettere il campo oi dati membri della classe.
Di seguito sono elencati i metodi forniti dalla classe Field per la riflessione di un campo.
Metodo | Descrizione |
---|---|
getField ('fieldName') | Restituisce il campo (pubblico) con un nome di campo specificato. |
getFields () | Restituisce tutti i campi pubblici (sia per la classe che per la superclasse). |
getDeclaredFields () | Recupera tutti i campi della classe. |
getModifier () | Restituisce una rappresentazione intera del modificatore di accesso del campo. |
set (classObject, value) | Assegna il valore specificato al campo. |
get (classObject) | Recupera il valore del campo. |
setAccessible(boolean) | Rendi il campo privato accessibile passando true. |
getDeclaredField ('fieldName') | Restituisce il campo con un nome specificato. |
Di seguito sono riportati due esempi di riflessione che dimostrano la riflessione sul campo pubblico e privato.
Il programma Java di seguito mostra la riflessione su un campo pubblico.
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(); } } }
Produzione
In questo programma, abbiamo dichiarato una classe 'Studente' con un campo pubblico StudentName. Quindi utilizzando l'interfaccia API della classe Field, eseguiamo la riflessione sul campo StudentName e recuperiamo il suo modificatore di accesso e il suo valore.
Il programma successivo esegue la riflessione su un campo privato della classe. Le operazioni sono simili tranne per il fatto che è stata effettuata una chiamata di funzione aggiuntiva per il campo privato. Dobbiamo chiamare setAccessible (true) per il campo privato. Quindi eseguiamo la riflessione su questo campo in modo simile al campo pubblico.
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(); } } }
Produzione
Riflessione: metodo
Analogamente ai campi della classe, possiamo anche eseguire la riflessione sui metodi della classe e modificare il loro comportamento in fase di esecuzione. Per questo, usiamo la classe Method del pacchetto java.lang.reflect.
Di seguito sono elencate le funzioni fornite dalla classe Method per la riflessione del metodo di classe.
Metodo | Descrizione |
---|---|
getMethods () | Recupera tutti i metodi pubblici definiti nella classe e nella relativa superclasse. |
getDeclaredMethod () | Restituisce metodi dichiarati nella classe. |
getName () | Restituisce i nomi dei metodi. |
getModifiers () | Restituisce una rappresentazione intera del modificatore di accesso del metodo. |
getReturnType () | Restituisce il tipo di ritorno del metodo. |
L'esempio seguente mostra il riflesso dei metodi di classe in Java utilizzando le API precedenti.
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(); } } }
Produzione
Nel programma sopra, vediamo che il metodo getDeclaredMethods restituisce l'array di metodi dichiarati dalla classe. Quindi iteriamo attraverso questo array e visualizziamo le informazioni di ciascun metodo.
Riflessione: costruttore
Possiamo usare la classe 'Constructor' del pacchetto java.lang.reflect per ispezionare e modificare i costruttori di una classe Java.
La classe del costruttore fornisce i seguenti metodi a questo scopo.
Metodo | Descrizione |
---|---|
getConstructors () | Restituisce tutti i costruttori dichiarati nella classe e nella relativa superclasse. |
getDeclaredConstructor () | Restituisce tutti i costruttori dichiarati. |
getName () | Recupera il nome del costruttore. |
getModifiers () | Restituisce la rappresentazione intera del modificatore di accesso dei costruttori. |
getParameterCount () | Restituisce il numero totale di parametri per un costruttore. |
L'esempio di riflessione seguente mostra il riflesso dei costruttori di una classe in Java. Come la riflessione sul metodo, anche qui il metodo getDeclaredConstructors restituisce un array di costruttori per una classe. Quindi attraversiamo questo array del costruttore per visualizzare le informazioni su ciascun costruttore.
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(); } } }
Produzione
Inconvenienti della riflessione
La riflessione è potente, ma non dovrebbe essere usata indiscriminatamente. Se è possibile operare senza utilizzare la riflessione, è preferibile evitare di utilizzarlo.
Di seguito sono elencati alcuni inconvenienti di Reflection:
- Spese generali di prestazione: Sebbene la riflessione sia una caratteristica potente, le operazioni riflettenti hanno ancora prestazioni più lente rispetto alle operazioni non riflettenti. Quindi dovremmo evitare di utilizzare i riflessi in applicazioni critiche per le prestazioni.
- Restrizioni di sicurezza: Poiché la riflessione è una funzionalità di runtime, potrebbe richiedere autorizzazioni in fase di esecuzione. Quindi, per le applicazioni che richiedono che il codice venga eseguito in un'impostazione di sicurezza limitata, la riflessione potrebbe non essere di alcuna utilità.
- Esposizione di interni: Usando la riflessione, possiamo accedere a campi e metodi privati in una classe. Così la riflessione rompe l'astrazione che potrebbe rendere il codice non portabile e disfunzionale.
Domande frequenti
D # 1) Perché Reflection viene utilizzato in Java?
Risposta: Usando la reflection possiamo ispezionare classi, interfacce, costruttori, campi e metodi in fase di esecuzione, anche se sono anonimi in fase di compilazione. Questa ispezione ci consente di modificare il comportamento di queste entità in fase di esecuzione.
Q # 2) Dove viene utilizzata la riflessione?
Risposta: La riflessione viene utilizzata nella scrittura di framework che interagiscono con classi definite dall'utente, in cui il programmatore non sa nemmeno quali saranno le classi o altre entità.
Q # 3) Java Reflection è lento?
Risposta: Sì, è più lento del codice di non riflessione.
Q # 4) Java Reflection è dannoso?
Risposta: In un certo senso, sì. Prima di tutto, perdiamo la sicurezza in fase di compilazione. Senza la sicurezza in fase di compilazione, potremmo ricevere errori in fase di esecuzione che potrebbero influire sugli utenti finali. Sarà anche difficile eseguire il debug dell'errore.
Q # 5) Come si interrompe una riflessione in Java?
Risposta: Evitiamo semplicemente di usare la riflessione scrivendo operazioni di non riflessione. O forse possiamo usare alcuni meccanismi generici come una convalida personalizzata con riflessione.
Ulteriori informazioni su Java Reflection
Il pacchetto java.lang.reflect ha le classi e le interfacce per fare la riflessione. E java.lang.class può essere utilizzato come punto di ingresso per la riflessione.
Come ottenere gli oggetti della classe:
1. Se hai un'istanza di un oggetto,
classe c = obj.getclass ();
2. Se conosci il tipo di lezione,
classe c = type.getClass ();
3. Se conosci il nome della classe,
Classe c = Class.forName ('com.demo.Mydemoclass');
Come coinvolgere i membri della classe:
I membri della classe sono campi (variabili di classe) e metodi.
- getFields () - Utilizzato per ottenere tutti i campi tranne i campi privati.
- getDeclaredField () - Utilizzato per ottenere i campi privati.
- getDeclaredFields () - Utilizzato per ottenere i campi privato e pubblico.
- getMethods () - Utilizzato per ottenere tutti i metodi tranne i metodi privati.
- getDeclaredMethods () –Utilizzato per ottenere i metodi pubblico e privato.
Programmi demo:
ReflectionHelper.java:
Questa è la classe in cui esamineremo utilizzando l'API di riflessione.
java coding intervista domande e risposte per esperti
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()); } }}
Conclusione
Questo tutorial ha spiegato in dettaglio l'API di Reflection in Java. Abbiamo visto come eseguire la riflessione di classi, interfacce, campi, metodi e costruttori insieme ad alcuni inconvenienti della riflessione.
La riflessione è una funzionalità relativamente avanzata in Java, ma dovrebbe essere utilizzata dai programmatori che hanno una roccaforte sul linguaggio. Questo perché potrebbe causare errori e risultati imprevisti se non utilizzato con cautela.
Sebbene la riflessione sia potente, dovrebbe essere usata con attenzione. Tuttavia, utilizzando la riflessione possiamo sviluppare applicazioni che non sono a conoscenza di classi e altre entità fino al runtime.
=> Dai un'occhiata alla guida per principianti di Java qui.
Lettura consigliata
- Tutorial di classe per scanner Java con esempi
- Java Integer e Java BigInteger Class con esempi
- Tutorial JAVA per principianti: oltre 100 tutorial video Java pratici
- Introduzione al linguaggio di programmazione Java - Tutorial video
- Cos'è Java Vector | Tutorial Java Vector Class con esempi
- Tutorial sull'interfaccia Java e sulla classe astratta con esempi
- Metodo Java substring () - Tutorial con esempi
- Tutorial di Java Collections Framework (JCF)