Java Reflection (riflessione JAVA) dettagliata


La riflessione è l'unico linguaggio di programmazione Java, delle caratteristiche, che permette di eseguire programmi Java sul loro controllo, o "auto-esame", e può attribuire direttamente alle procedure operative interne.Ad esempio, si può ottenere un nome di classe Java di ogni membro e display.

Java, l'applicazione pratica di questa capacità può essere utilizzata non sono molti, ma in altri linguaggi di programmazione di questa funzione semplicemente non esiste.Ad esempio, Pascal, C o C + +, non vi è alcun modo per ottenere la definizione di funzione nelle informazioni relative al programma.

JavaBean è un riflesso della applicazione pratica, permette di strumenti per la visualizzazione di funzionamento dei componenti software.Questi strumenti vengono caricati in modo dinamico attraverso la riflessione e ricevi i componenti Java (classi) della proprietà.

1. Un semplice esempio

Si consideri il seguente esempio semplice, vediamo come il riflesso di lavoro.


importazione java.lang.reflect .*;
pubblico DumpMethods classe {
public static void main (String args []) {
try {
Classe C = Class.forName (args [0]);
m Metodo [] = c.getDeclaredMethods ();
for (int i = 0; i m.length ; i + +)
System.out.println (m [i] ToString ().);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Istruzione viene eseguita nel modo seguente:
java DumpMethods java.util.Stack

E 'l'output risultante è:
java.lang.Object java.util.Stack.push pubblico (java.lang.Object)

pubblico java.util.Stack.pop java.lang.Object sincronizzato ()

pubblico java.util.Stack.peek java.lang.Object sincronizzato ()

boolean java.util.Stack.empty pubblica ()

pubblico java.util.Stack.search int sincronizzato (java.lang.Object)

Questo elenca il nome di ciascuna classe java.util.Stack metodo e la loro qualificazione e il tipo di ritorno.

Questo programma utilizza Class.forName caricare la classe specificata, quindi telefonare per avere questa classe getDeclaredMethods definisce un elenco di metodo.java.lang.reflect.Methods è usato per descrivere un singolo metodo di una classe di una classe.


2. Riflessione introduttiva

Per la riflessione della classe, quali il metodo, può essere trovato nel pacchetto java.lang.relfect.Quando si utilizzano queste classi deve seguire tre fasi: Il primo passo è quello di ottenere la classe che si vuole operare oggetto java.lang.Class.L'esecuzione del programma Java, con la classe java.lang.Class per descrivere le classi e le interfacce.

Ecco i metodi per ottenere un oggetto di classe:
Classe C = Class.forName ("java.lang.String");

Questa dichiarazione per ottenere un oggetto di classe String classe.C'è un altro modo, come la seguente dichiarazione:
Classe C = int.class;

O
Classe C = Integer.TYPE;

Ricevono tipi di base di informazioni sulla classe.Visitate uno dei ultimo metodo è il tipo di base del pacchetto (ad esempio Integer) nel campo pre-tipo definito.

Il secondo passo è quello di chiamare il metodo, come getDeclaredMethods per ottenere tutti i metodi definiti nella classe lista.

Dopo aver ottenuto queste informazioni, la terza fase può essere effettuata - e utilizzare l'API di riflessione per manipolare le informazioni, come ad esempio il seguente codice:
Classe C = Class.forName ("java.lang.String");

m Metodo [] = c.getDeclaredMethods ();

System.out.println (m [0] ToString ().);

Verrà stampata come metodo String testo definito il primo prototipo.

Nell'esempio riportato di seguito, i tre passi per affrontare le applicazioni specifiche di riflessione per fornire esempi.

Analog operatore instanceof

Dopo avere informazioni di classe, di solito il passo successivo è quello di risolvere sull'oggetto classe di alcune questioni fondamentali.Ad esempio, Class.isInstance metodo può essere utilizzato per simulare l'operatore instanceof:
class A {
}

public class {instance1
public static void main (String args []) {
try {
Classe CLS = Class.forName ("A");
boolean b1 = cls.isInstance (new Integer (37));
System.out.println (b1);
boolean b2 = cls.isInstance (A new ());
System.out.println (b2);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

In questo esempio viene creata una classe di oggetti di classe A e quindi verificare se un oggetto è un'istanza di A.Integer (37) non è, ma la nuova A () è.


3. Per trovare i metodi della classe

Trova una classe definisce quali sono i metodi, questo è un uso molto preziosa di riflessione molto semplice.Il seguente codice realizza questo tipo di utilizzo:
importazione java.lang.reflect .*;

public class {Method1
private int f1 (p Object, int x) throws NullPointerException {
if (p == null)
gettare nuova NullPointerException ();
ritorno x;
}

public static void main (String args []) {
try {
Classe CLS = Class.forName ("method1");
methlist Metodo [] = cls.getDeclaredMethods ();
for (int i = 0; i methlist.length ; i + +) {
Metodo m = methlist [i];
System.out.println ("name =" + m.getName ());
System.out.println ("classe decl =" + m.getDeclaringClass ());
Classe pvec [] = m.getParameterTypes ();
for (int j = 0; pvec.length j ; j + +)
System.out.println ("param #" + j + "" + pvec [j]);
Classe EVEC [] = m.getExceptionTypes ();
for (int j = 0; evec.length j ; j + +)
System.out.println ("IVA escl #" + j + "" + EVEC [j]);
System.out.println ("tipo di ritorno =" + m.getReturnType ());
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (E);
}
}
}

Questo programma prima ottenere una descrizione di Method1 classe, quindi chiamare getDeclaredMethods per ottenere una serie di oggetti metodo, che sono definite nella classe descrivere ognuno dei metodi, compresi i metodi pubblici, i metodi di protezione, i metodi pacchetto privati e metodi.Se si utilizza il programma per sostituire getDeclaredMethods GetMethods, è possibile ottenere tutti i metodi ereditati.

Metodo per ottenere un elenco di oggetti, i parametri di questi metodi per mostrare il tipo di tipi di eccezione e di tipi di valore di ritorno non è difficile.Questi tipi sono il tipo di base o del tipo di classe, in grado di descrivere la classe di oggetti con l'ordine dato.

L'output è il seguente:
name = f1

decl class = classe method1

param # 0 java.lang.Object classe

param # 1 int

exc # 0 classe java.lang.NullPointerException

ritorno type = int

-----
name = principale

decl class = classe method1

param # 0 classe [Ljava.lang.String;

ritorno type = void


4. Ottenere informazioni costruttore

costruttore della classe per l'utilizzo di quanto sopra per l'uso di metodi simili, come:
importazione java.lang.reflect .*;

public class {constructor1
pubblico constructor1 () {
}

protetto constructor1 (int i, doppio d) {
}

public static void main (String args []) {
try {
Classe CLS = Class.forName ("constructor1");
Costruttore ctorlist [] cls.getDeclaredConstructors = ();
for (int i = 0; i ctorlist.length ; i + +) {
Costruttore ct = ctorlist [i];
System.out.println ("name =" + ct.getName ());
System.out.println ("classe decl =" + ct.getDeclaringClass ());
Classe pvec [] = ct.getParameterTypes ();
for (int j = 0; pvec.length j ; j + +)
System.out.println ("param #" + j + "" + pvec [j]);
Classe EVEC [] = ct.getExceptionTypes ();
for (int j = 0; evec.length j ; j + +)
System.out.println ("IVA escl #" + j + "" + EVEC [j]);
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Questo caso non tornare il tipo di informazioni, è perché il costruttore non ritorna tipo.

Risultato di funzionamento di questo programma:
name = constructor1

decl class = classe constructor1

-----
name = constructor1

decl class = classe constructor1

param # 0 int

param # 1 doppio


5. Per il campo di classe (dominio)

Trova una classe definisce quali campi di dati sono possibili, il codice seguente sull'asciutto questa cosa:
importazione java.lang.reflect .*;

public class {campo1
doppie private d;
pubblico i static int finale = 37;
String s = "prova";

public static void main (String args []) {
try {
Classe CLS = Class.forName ("campo1");
Campo FieldList [] cls.getDeclaredFields = ();
for (int i = 0; i fieldlist.length ; i + +) {
Campo fld = FieldList [i];
System.out.println ("name =" + fld.getName ());
System.out.println ("classe decl =" + fld.getDeclaringClass ());
System.out.println ("type =" + fld.getType ());
int mod fld.getModifiers = ();
System.out.println ("modificatori =" + Modifier.toString (mod));
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Questo esempio e 'molto simile all'esempio precedente.Esempio, utilizza una cosa nuova Modifier, è anche una classe di riflessione, i membri del modificatore utilizzato per descrivere il campo, come "int privato".Questi modificatori descritto dallo stesso numero intero, e l'uso Modifier.toString per tornare alla descrizione "ufficiale" l'ordine della stringa (come "statico" in "finale" prima).Output di questo programma è il seguente:
name = d

decl class = classe campo1

tipo = doppio

modificatori = privato

-----
name = i

decl class = classe campo1

tipo = int

modificatori = finale statico pubblico

-----
name = s

decl class = classe campo1

tipo = java.lang.String classe

modificatori =

La situazione e cercare modi per ottenere il campo può essere raggiunto solo quando la classe allo stato attuale delle informazioni di settore (getDeclaredFields), oppure è possibile ottenere la classe padre definisce i campi (getFields).


6. Secondo il nome del metodo del metodo

Testo qui, senza eccezione, tutti gli esempi e le modalità per ottenere informazioni sulla classe.Possiamo anche utilizzare la reflection per fare altre cose, come ad esempio il metodo di attuazione di specificare un nome.Nell'esempio riportato di seguito viene illustrato il seguente:
importazione java.lang.reflect .*;
public class {method2
public int add (int a, int b) {
ritorno a + b;
}
public static void main (String args []) {
try {
Classe CLS = Class.forName ("method2");
Classe partypes [] = new Class [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Metodo meth = cls.getMethod ("add", partypes);
method2 methobj method2 = new ();
Oggetto arglist [] = new Object [2];
arglist [0] = new Integer (37);
arglist [1] = new Integer (47);
Oggetto retobj = meth.invoke (methobj, arglist);
retval = Integer (Intero) retobj;
System.out.println (retval.intValue ());
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Se da qualche parte nella realizzazione di un programma quando è consapevole della necessità di eseguire un metodo, questo metodo è il nome del programma è in esecuzione in cui (per esempio, l'ambiente di sviluppo JavaBean farebbe una cosa del genere), poi la procedura di cui sopradimostra come farlo.

L'esempio sopra riportato, GetMethod utilizzato per trovare due parametri interi e un metodo chiamato aggiungere.Trovare il metodo e creare l'oggetto corrispondente metodo, l'istanza in oggetto il diritto di eseguirla.L'implementazione del metodo, la necessità di fornire un elenco di parametri, che nell'esempio sopra è un numero intero, rispettivamente, 37 e 47 giri di due oggetti Integer.metodo di esecuzione è un numero intero restituire l'oggetto stesso, che incapsula il valore di ritorno di 84 anni.


7. Per creare un nuovo oggetto

Per il costruttore, non ti piace l'applicazione di metodi, perché significa la realizzazione di un costruttore crea un nuovo oggetto (per essere precisi, il processo di creazione di un oggetto particolare l'assegnazione di memoria e costruire un oggetto.)Così, con l'esempio più simile del precedente esempio come segue:
importazione java.lang.reflect .*;

public class {constructor2
pubblico constructor2 () {
}

pubblico constructor2 (int a, int b) {
System.out.println ("a =" + a + "b =" + b);
}

public static void main (String args []) {
try {
Classe CLS = Class.forName ("constructor2");
Classe partypes [] = new Class [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Costruttore ct = cls.getConstructor (partypes);
Oggetto arglist [] = new Object [2];
arglist [0] = new Integer (37);
arglist [1] = new Integer (47);
Oggetto ct.newInstance retobj = (arglist);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Secondo il tipo di parametro specificato per trovare il costruttore appropriato ed eseguirlo per creare una nuova istanza di oggetto.Questo metodo può essere utilizzato in fase di esecuzione per creare dinamicamente l'oggetto, piuttosto che creare oggetti in fase di compilazione, che è molto prezioso.


8. Modificare il campo (campo) del valore

Vi è anche una riflessione utile dell'oggetto è di cambiare il campo Dati valore.riflessione da un programma in esecuzione per trovare gli oggetti in base al nome nel campo e modificarlo, il seguente esempio per illustrare questo punto:
importazione java.lang.reflect .*;

public class {Campo2
public double d;

public static void main (String args []) {
try {
Classe CLS = Class.forName ("campo2");
Campo FLD cls.getField = ("d");
campo2 f2obj campo2 = new ();
System.out.println ("d =" + f2obj.d);
fld.setDouble (f2obj, 12,34);
System.out.println ("d =" + f2obj.d);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Questo esempio, il valore del campo è cambiata d 12.34.


9. Uso degli array

Questo articolo descrive il riflesso della operazione finale è quello di creare un array di utilizzo.Array in linguaggio Java è un tipo speciale di classe, un riferimento ad array può essere assegnato riferimento all'oggetto.Guardate il seguente esempio per vedere come il lavoro della matrice:
importazione java.lang.reflect .*;

public class {array1
public static void main (String args []) {
try {
Classe CLS = Class.forName ("java.lang.String");
Oggetto arr = Array.newInstance (cls, 10);
Array.set (arr, 5, "Questa è una prova");
String s = (String) Array.get (, arr 5);
System.out.println (s);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Casi di 10 unità per creare un array di stringhe di lunghezza, per le prime 5 posizioni della stringa assegnato un valore, e, infine, ottenere la stringa dalla matrice e stamparla.

Il codice seguente fornisce un esempio più complesso:
importazione java.lang.reflect .*;

public class {array2
public static void main (String args []) {
dim int [] = new int [] {5, 10, 15};
Oggetto arr = Array.newInstance (Integer.TYPE, dim);
Oggetto arrobj = Array.get (arr, 3);
Classe CLS = arrobj.getClass () GetComponentType ().
System.out.println (CLS);
arrobj = Array.get (arrobj, 5);
Array.setInt (arrobj, 10, 37);
arrcast [][][] int = (int arr [][][]);
System.out.println (arrcast [3] [5] [10]);
}
}

Nell'esempio viene creato un 5 x 10 x 15 array di interi, e in [3] [5] [10] assegnato un valore di 37 elementi.Si noti che gli array multidimensionali sono in realtà array di array, per esempio, dopo la prima Array.get, arrobj è un array di 10 x 15.Allora uno degli elementi, cioè, una matrice di lunghezza 15, e l'uso Array.setInt per i suoi primi 10 elementi della cessione.

Si noti che quando si crea il tipo di matrice è dinamica, in fase di compilazione non conosce il suo tipo.