Java Reflection (JAVA reflektion) Detaljerade


Reflektion är programmeringsspråket Java en av de egenskaper som gör det möjligt att köra Java-program på deras egna kontroller, eller "självrannsakan," och kan tillskriva till det interna procedurer.Till exempel kan det bli en Java klass namnet på varje medlem och display.

Java, får i den praktiska tillämpningen av denna funktion ska användas är inte många, men i andra programmeringsspråk här funktionen helt enkelt inte existerar.Till exempel, Pascal, C eller C + +, finns det inget sätt att få funktionen definitionen i information som gäller programmet.

JavaBean är en återspegling av den praktiska tillämpningen, gör det visualiseringsverktyg operativsystem komponenter.Dessa verktyg läses in dynamiskt genom reflektion och få Java komponenter (klasser) av fastigheten.

1. Ett enkelt exempel

Betrakta följande enkla exempel, låt oss se hur arbetet eftertanke.


import java.lang.reflect .*;
public class DumpMethods {
public void main (String args []) {
try {
Klass C = Class.forName (args [0]);
Metod m [] = c.getDeclaredMethods ();
for (int i = 0; i m.length; i + +)
System.out.println (m [i] toString ().)
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Sats körs enligt följande:
java DumpMethods java.util.Stack

Det är den resulterande produktion är:
offentliga java.lang.Object java.util.Stack.push (java.lang.Object)

offentliga synkroniserade java.lang.Object java.util.Stack.pop ()

offentliga synkroniserade java.lang.Object java.util.Stack.peek ()

public boolean java.util.Stack.empty ()

offentliga synkroniserade int java.util.Stack.search (java.lang.Object)

Detta listar namnet på varje metod java.util.Stack klass och deras kval och returtyp.

Detta program använder Class.forName att läsa den angivna klassen, sedan ringa för att få detta getDeclaredMethods klass definierar en metod lista.java.lang.reflect.Methods används för att beskriva en enda metod för en klass av en klass.


2. Igång reflektion

För reflektion av klass, såsom metoder, finns i java.lang.relfect paketet.När du använder dessa klasser måste följa tre steg: Det första steget är att få den klass du vill styra java.lang.Class objekt.Körs i Java-programmet, med java.lang.Class klassen att beskriva klasser och gränssnitt.

Här är att få en klass metoder objekt:
Klass C = Class.forName ("java.lang.String");

Detta uttalande för att få ett String-objekt klass.Det finns ett annat sätt, med följande deklaration:
Klass C = int.class;

Eller
Klass C = Integer.TYPE;

De får grundläggande typer av kursinformation.Besök en av den senare metoden är den grundläggande typen av paket (som heltal) i de fördefinierade Typ-fältet.

Det andra steget är att ringa metoden, såsom getDeclaredMethods att få alla metoder som definierats i klassen listan.

När du har fått denna information kan det tredje steget skall genomföras - och använda reflektion API för att manipulera information, t.ex. följande kod:
Klass C = Class.forName ("java.lang.String");

Metod m [] = c.getDeclaredMethods ();

System.out.println (m [0] toString ().)

Det kommer att skriva ut som textsträng som definieras i den första prototypen.

I exemplet nedan har de tre stegen för att hantera specifika program för att använda reflektion som ett exempel.

Analog instanceof operatör

Efter få klass information, vanligtvis nästa steg är att besluta om klass föremål för några grundläggande frågor.Till exempel kan Class.isInstance metod används för att simulera instanceof operatören:
class A {
}

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

I det här exemplet skapas en klass av klass A objekt, och sedan kontrollera om något objekt är en instans av A.Integer (37) är det inte, men det nya A () är.


3. För att hitta metoder i klassen

Hitta en klass definierar vilka metoder, är detta en mycket värdefull användning av mycket grundläggande reflektion.Följande kod åstadkommer detta användande:
import java.lang.reflect .*;

public class method1 {
private int F1 (Object p, int x) kastar NullPointerException {
if (p == null)
kasta nytt NullPointerException ();
retur x;
}

public void main (String args []) {
try {
Klass CLS = Class.forName ("method1");
Metod methlist [] = cls.getDeclaredMethods ();
for (int i = 0; i methlist.length; i + +) {
Metod m = methlist [i];
System.out.println ("name =" + m.getName ());
System.out.println ("decl class =" + m.getDeclaringClass ());
Klass pvec [] = m.getParameterTypes ();
for (int j = 0, j pvec.length, j + +)
System.out.println ("param #" + j + "" + pvec [j]);
Klass evec [] = m.getExceptionTypes ();
for (int j = 0, j evec.length, j + +)
System.out.println ("ex moms #" + j + "" + evec [j]);
System.out.println ("return type =" + m.getReturnType ());
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Detta program får första en beskrivning av method1 klass, sedan ringa getDeclaredMethods att få en serie av metod objekt, som definieras i klassen beskriva varje av metoder, inklusive offentliga metoder, skyddade metoder, paket privata metoder och metoder.Om du använder programmet för att ersätta getMethods getDeclaredMethods kan du få alla ärvda metoder.

Metod för att få en lista över objekt, de parametrar av dessa metoder visa vilken typ av undantag typer och returtyper värde inte svårt.Dessa typer är de grundläggande typ eller klass typ, kan beskriva den klass av objekt av angiven ordning.

Utgången är enligt följande:
name = f1

decl class = klass method1

param # 0 klass java.lang.Object

param # 1 int

exc # 0 klass java.lang.NullPointerException

returtyp = int

-----
name = viktigaste

decl class = klass method1

param # 0 klass [Ljava.lang.String;

returtyp = ogiltig


4. Få konstruktören information

Klasskonstruktorn för användning av ovanstående för användning av liknande metoder, såsom:
import java.lang.reflect .*;

public class constructor1 {
offentliga constructor1 () {
}

skyddade constructor1 (int i, dubbel d) {
}

public void main (String args []) {
try {
Klass CLS = Class.forName ("constructor1");
Konstruktör ctorlist [] = cls.getDeclaredConstructors ();
for (int i = 0; i ctorlist.length; i + +) {
Konstruktör ct = ctorlist [i];
System.out.println ("name =" + ct.getName ());
System.out.println ("decl class =" + ct.getDeclaringClass ());
Klass pvec [] = ct.getParameterTypes ();
for (int j = 0, j pvec.length, j + +)
System.out.println ("param #" + j + "" + pvec [j]);
Klass evec [] = ct.getExceptionTypes ();
for (int j = 0, j evec.length, j + +)
System.out.println ("ex moms #" + j + "" + evec [j]);
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Detta fall inte får tillbaka den typ av information, beror det på att entreprenören inte returtyp.

Resultatet av att köra:
name = constructor1

decl class = klass constructor1

-----
name = constructor1

decl class = klass constructor1

param # 0 int

param # 1 dubbel


5. För klassen fältet (domän)

Hitta en klass definierar vilka data fält är också möjligt, följande kod i den torra denna sak:
import java.lang.reflect .*;

public class fält1 {
privata dubbelrum d;
public static final int i = 37;
String s = "test";

public void main (String args []) {
try {
Klass CLS = Class.forName ("fält1");
Fält fieldlist [] = cls.getDeclaredFields ();
for (int i = 0; i fieldlist.length; i + +) {
Fält Fld = fieldlist [i];
System.out.println ("name =" + fld.getName ());
System.out.println ("decl class =" + fld.getDeclaringClass ());
System.out.println ("type =" + fld.getType ());
int mod = fld.getModifiers ();
System.out.println ("modifierare =" + Modifier.toString (mod));
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Detta exempel och är mycket lik det tidigare exemplet.Exempelvis använder en ny sak modifier, är det också en reflektion klass, medlemmarna i modifierare används för att beskriva området, såsom "private int".Dessa modifierare beskrivs av heltal själv, och användningen Modifier.toString att återvända till den "officiella" beskrivning av ordningen på strängen (som "statisk" i den "slutliga" innan).Utdata från detta program är:
name = d

decl class = klass fält1

type = dubbel

modifierare = privat

-----
name = jag

decl class = klass fält1

type = int

modifierare = public static final

-----
name = s

decl class = klass fält1

type = klass java.lang.String

modifierare =

Situationen och leta efter sätt att få fältet kan uppnås först när klassen i det nuvarande läget i området information (getDeclaredFields), eller så kan du få den överordnade klassen definierar fält (getfields).


6. Enligt den metod namnet på metoden

Text här, utan undantag, att alla exempel och hur få information om klassen.Vi kan också använda reflektion att göra några andra saker, exempelvis genomförandet metod för att specificera ett namn.Följande exempel visar följande:
import java.lang.reflect .*;
public class method2 {
public int add (int a, int b) {
återgå A + B;
}
public void main (String args []) {
try {
Klass CLS = Class.forName ("method2");
Klass partypes [] = new Klass [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Metod meth = cls.getMethod ("add", partypes);
method2 methobj = new method2 ();
Object arglist [] = new Object [2];
arglist [0] = new Integer (37);
arglist [1] = new Integer (47);
Objekt retobj = meth.invoke (methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println (retval.intValue ());
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Om någonstans i genomförandet av ett program när den är medveten om behovet av att utföra en metod är denna metod namnet på programmet körs i den angivna (till exempel, skulle JavaBean utvecklingsmiljö göra en sådan sak), sedan proceduren ovanvisar hur man gör det.

Exemplet ovan, getMethod används för att hitta två heltal parametrar och en metod som heter Lägg till.Hitta metoden och skapa motsvarande metod objektet, objektets exempel rätten att utföra det.Genomförandet av metoden, behovet att tillhandahålla en förteckning över parametrar, som i exemplet ovan är ett heltal respektive wraps 37 och 47 i två Integer-objekt.Utförande metoden är ett heltal returnerar samma objekt, som kapslar in det returnerade värdet på 84.


7. Vill skapa ett nytt objekt

För konstruktören, gillar du inte att metoder, eftersom det innebär att genomföra en konstruktor skapar ett nytt objekt (för att vara exakt, processen för att skapa ett objekt och fördelning av minne och konstruera ett objekt).Så, med de mest liknande exempel från föregående exempel enligt följande:
import java.lang.reflect .*;

public class constructor2 {
offentliga constructor2 () {
}

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

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

Enligt den angivna parametern skriva för att hitta lämpliga konstruktören och köra den för att skapa ett nytt objekt instans.Denna metod kan användas vid körning för att dynamiskt skapa objektet, snarare än att skapa objekt vid kompileringen, vilket är mycket värdefullt.


8. Ändra fält (fält) värde

Det finns också en användbar bild av syftet är att ändra värdet datafältet.reflektion från en som kör program för att hitta objekt med namn i fältet och ändra det, följande exempel för att illustrera detta:
import java.lang.reflect .*;

public class field2 {
offentliga dubbel D;

public void main (String args []) {
try {
Klass CLS = Class.forName ("field2");
Fält Fld = cls.getField ("d");
field2 f2obj = new field2 ();
System.out.println ("d =" + f2obj.d);
fld.setDouble (f2obj, 12,34);
System.out.println ("d =" + f2obj.d);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Detta exempel är fältets värde ändrats av d 12,34.


9. Använda vektorer

Den här artikeln beskriver återspegling av den slutliga transaktionen är att skapa en array av användning.Array i Java är en speciell klass typ, kan en matris referens tilldelas Objektreferensen.Titta på följande exempel för att se hur arbetet i matrisen:
import java.lang.reflect .*;

public class matris1 {
public void main (String args []) {
try {
Klass CLS = Class.forName ("java.lang.String");
Objekt arr = Array.newInstance (CLS, 10);
Array.set (arr, 5, "detta är ett test");
String s = (String) Array.get (arr, 5);
System.out.println (s),
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Fall av 10 enheter för att skapa en String array av längd, för den första 5 positioner i strängen tilldelas ett värde, och äntligen få strängen från arrayen och skriva ut den.

Följande kod ger ett mer avancerat exempel:
import java.lang.reflect .*;

public class matris2 {
public void main (String args []) {
int tonas [] = new int [] {5, 10, 15};
Objekt arr = Array.newInstance (Integer.TYPE skymmer);
Objekt arrobj = Array.get (arr, 3);
Klass CLS = arrobj.getClass () GetComponentType ().
System.out.println (CLS);
arrobj = Array.get (arrobj, 5);
Array.setInt (arrobj, 10, 37);
int arrcast [][][] = (int [][][]) arr;
System.out.println (arrcast [3] [5] [10]);
}
}

Exempel skapas en 5 x 10 x 15 heltalsmatris, och i [3] [5] [10] tilldelas ett värde av 37 element.Observera att flerdimensionella arrayer faktiskt arrayer av arrayer, till exempel efter den första Array.get är arrobj en 10 x 15 matris.Då kan du få en av de aspekter, dvs en array med längden 15, och använda Array.setInt för sina 10 första delarna av uppdraget.

Observera att när du skapar arrayen typ är dynamisk, vid kompileringen inte vet sitt slag.