Java Refleksjon (JAVA refleksjon) Detaljert


Refleksjon er det Java programmeringsspråk en av karakteristikkene, som gjør det mulig å kjøre Java-programmer på sin egen inspeksjon, eller "self-eksamen," og kan attributt direkte til den interne operative prosedyrer.For eksempel, kan det bli en Java klasse navnet på hvert medlem og display.

Java, kan i den praktiske anvendelsen av denne muligheten skal benyttes er ikke mange, men i andre programmeringsspråk denne funksjonen rett og slett ikke eksisterer.For eksempel, Pascal, C eller C + +, er det ingen måte å få funksjonen definisjonen i programmet-relatert informasjon.

JavaBean er en refleksjon av den praktiske anvendelsen, lar det visualiseringsverktøy opererer programvarekomponenter.Disse verktøyene er lastes dynamisk gjennom refleksjon og få Java-komponenter (klasser) av eiendommen.

En. Et enkelt eksempel

Vurder følgende enkle eksempel, la oss se hvordan arbeidet refleksjon.


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

Statement er utført som følger:
java DumpMethods java.util.Stack

Det er den resulterende utdataene:
offentlig java.lang.Object java.util.Stack.push (java.lang.Object)

offentlige synkronisert java.lang.Object java.util.Stack.pop ()

offentlige synkronisert java.lang.Object java.util.Stack.peek ()

public boolean java.util.Stack.empty ()

offentlige synkronisert int java.util.Stack.search (java.lang.Object)

Dette viser navnet på hver metode java.util.Stack klasse og deres kvalifiseringskamp og tilbake type.

Dette programmet bruker Class.forName laste den angitte klassen, så ring å få denne getDeclaredMethods klassen definerer en metode liste.java.lang.reflect.Methods brukes til å beskrive en enkelt metode for en klasse med en klasse.


2. Startet Refleksjon

For refleksjon av klassen, slik som metode, kan finnes i java.lang.relfect pakken.Når du bruker disse klassene må følge tre trinn: Første skritt er å få den klassen du vil betjene java.lang.Class objektet.Kjører i Java-program, med java.lang.Class klassen å beskrive klasser og grensesnitt.

Her er å få en klasse objekt metoder:
Klasse C = Class.forName ("java.lang.String");

Denne setningen til å få en String klassen klasse objektet.Det er en annen måte, som følgende uttalelse:
Klasse c = int.class;

Eller
Klasse c = Integer.TYPE;

De får grunnleggende typer av klasse informasjon.Besøk en av de siste metoden er den grunnleggende typen pakken (som heltall) i forhåndsdefinerte TYPE-feltet.

Det andre trinnet er å kalle metoden, for eksempel getDeclaredMethods å innhente alle metodene definert i klassen listen.

Når du har fått denne informasjonen, kan det tredje trinnet gjennomføres - og bruk refleksjon API for å manipulere informasjon, for eksempel følgende kode:
Klasse C = Class.forName ("java.lang.String");

Metode m [] = c.getDeclaredMethods ();

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

Den vil skrives ut som tekst, String metoden definert i den første prototypen.

I eksempelet nedenfor, de tre trinnene for å håndtere spesifikke applikasjoner for å bruke refleksjon for å gi eksempler.

Analog instanceof operatør

Etter få klassen informasjon, vanligvis neste skritt er å løse på Class gjenstand for noen grunnleggende spørsmål.For eksempel kan Class.isInstance metode brukes til å simulere instanceof operatør:
klasse A {
}

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

I dette eksemplet oppretter en klasse for klasse A objekter, og deretter sjekke om et objekt er en forekomst av A.Integer (37) er ikke, men den nye A () er.


Tre. For å finne klassen metoder

Finn en klasse definerer hvilke metoder, er dette en svært verdifull bruk av svært grunnleggende refleksjon.Følgende kode oppnår denne bruken:
import java.lang.reflect .*;

public class method1 {
private int f1 (Object p, int x) kaster NullPointerException {
if (p == null)
kaste nytt NullPointerException ();
avkastning x;
}

public static void main (String args []) {
try {
Klasse CLS = Class.forName ("method1");
Metode methlist [] = cls.getDeclaredMethods ();
for (int i = 0; i methlist.length; i + +) {
Metode m = methlist [i];
System.out.println ("name =" + m.getName ());
System.out.println ("dekl class =" + m.getDeclaringClass ());
Klasse PVEC [] = m.getParameterTypes ();
for (int j = 0; j pvec.length; j + +)
System.out.println ("param #" + j + "" + PVEC [j]);
Klasse evec [] = m.getExceptionTypes ();
for (int j = 0; j evec.length; j + +)
System.out.println ("exc #" + j + "" + evec [j]);
System.out.println ("avkastning type =" + m.getReturnType ());
System.out.println ("-----");
}
} Catch (Kan kastes e) {
System.err.println (e);
}
}
}

Dette programmet først få tak i en beskrivelse av method1 klasse, så ring getDeclaredMethods å få en serie av metode gjenstander, som er definert i klassen beskriver hver av metoder, herunder offentlige metoder, beskyttet metoder, pakke private og metoder.Hvis du bruker programmet til å erstatte getMethods getDeclaredMethods, kan du få all den arvede metoder.

Metode for å få en liste over objekter, av parameterne for disse metodene viser type unntak typer og returverdi typer ikke vanskelig.Disse typene er de grunnleggende type eller klasse type, kan beskrive klasse av objekter av pålegget gitt.

Utgangen er som følger:
name = f1

dekl class = klasse method1

param # 0 klassen java.lang.Object

param # 1 int

exc # 0 class java.lang.NullPointerException

Avkastningen type = int

-----
name = viktigste

dekl class = klasse method1

param # 0-klassen [Ljava.lang.String;

Avkastningen type = ugyldig


4. Get konstruktør informasjon

Klasse konstruktør for bruk av ovennevnte for bruk av lignende metoder, som for eksempel:
import java.lang.reflect .*;

public class constructor1 {
offentlig constructor1 () {
}

beskyttede constructor1 (int i, dobbel d) {
}

public static void main (String args []) {
try {
Klasse CLS = Class.forName ("constructor1");
Constructor ctorlist [] = cls.getDeclaredConstructors ();
for (int i = 0; i ctorlist.length; i + +) {
Constructor ct = ctorlist [i];
System.out.println ("name =" + ct.getName ());
System.out.println ("dekl class =" + ct.getDeclaringClass ());
Klasse PVEC [] = ct.getParameterTypes ();
for (int j = 0; j pvec.length; j + +)
System.out.println ("param #" + j + "" + PVEC [j]);
Klasse evec [] = ct.getExceptionTypes ();
for (int j = 0; j evec.length; j + +)
System.out.println ("exc #" + j + "" + evec [j]);
System.out.println ("-----");
}
} Catch (Kan kastes e) {
System.err.println (e);
}
}
}

Denne saken fikk ikke tilbake den type informasjon, er det fordi konstruktøren ikke retur-type.

Resultatet av å kjøre:
name = constructor1

dekl class = klasse constructor1

-----
name = constructor1

dekl class = klasse constructor1

param # 0 int

param # 1 dobbelt


5. For klassen feltet (domene)

Finn en klasse definerer hvilke data feltene er også mulig, følgende kode i den tørre denne saken:
import java.lang.reflect .*;

public class field1 {
private dobbel d;
public static final int i = 37;
String s = "testing";

public static void main (String args []) {
try {
Klasse CLS = Class.forName ("field1");
Field fieldlist [] = cls.getDeclaredFields ();
for (int i = 0; i fieldlist.length; i + +) {
Field Fld = fieldlist [i];
System.out.println ("name =" + fld.getName ());
System.out.println ("dekl class =" + fld.getDeclaringClass ());
System.out.println ("type =" + fld.getType ());
int mod = fld.getModifiers ();
System.out.println ("modifikatorer =" + Modifier.toString (mod));
System.out.println ("-----");
}
} Catch (Kan kastes e) {
System.err.println (e);
}
}
}

Dette eksempel og er svært lik den forrige eksempel.Eksempelvis bruker en ny ting Modifier, er det også en refleksjon klasse, medlemmene av modifier brukes til å beskrive feltet, for eksempel «private int".Disse modifikatorer beskrevet av heltall seg selv, og bruken Modifier.toString å gå tilbake til den "offisielle" beskrivelse av rekkefølgen på strengen (for eksempel "statisk" i "finalen" før).Produksjon av dette programmet er:
name = d

dekl class = klasse field1

type = dobbel

modifikatorer = private

-----
name = i

dekl class = klasse field1

type = int

modifikatorer = public static finalen

-----
name = s

dekl class = klasse field1

type = klassen java.lang.String

modifikatorer =

Situasjonen og ser etter måter å få feltet kan oppnås bare når klassen i den nåværende tilstand av feltet informasjon (getDeclaredFields), eller du kan få den overordnede klassen definerer feltene (getfields).


6. Ifølge metoden navnet på metoden

Tekst her, uten unntak, til alle eksempler og hvordan få informasjon om klassen.Vi kan også bruke refleksjon til å gjøre noen andre ting, som for eksempel gjennomføringen metode for å angi et navn.Det følgende eksemplet viser følgende:
import java.lang.reflect .*;
public class method2 {
public int add (int a, int b) {
returnere a + b;
}
public static void main (String args []) {
try {
Klasse CLS = Class.forName ("method2");
Klasse partypes [] = new Klasse [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Metode meth = cls.getMethod ("legg til", partypes);
method2 methobj = ny 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 (Kan kastes e) {
System.err.println (e);
}
}
}

Hvis et sted i gjennomføringen av et program når den er klar over behovet for å utføre en metode, er denne metoden navnet på programmet kjører i den angitte (for eksempel, ville JavaBean utviklingsmiljøet gjøre noe slikt), og deretter prosedyren ovenfordemonstrerer hvordan du gjør det.

Eksempelet ovenfor, getMethod brukes til å finne to heltall parametre og en metode som kalles legge.Finn metoden og opprette tilsvarende Method objektet, objektet forekomsten i retten til å utføre det.Gjennomføringen av metoden, behovet for en liste over parametere, som i eksempelet ovenfor er et heltall, henholdsvis, wraps 37 og 47 av to Integer objekter.Utførelsesmåte er et heltall tilbake samme objekt, som omslutter returverdien av 84.


7. Hvis du vil opprette et nytt objekt

For konstruktøren, at du ikke liker gjennomføringen av metoder, fordi det betyr at gjennomføringen av en konstruktør oppretter et nytt objekt (for å være nøyaktig, prosessen med å opprette et objekt herunder tildeling av minne og konstruerer et objekt).Så, med de mest lignende eksempel på forrige eksempel som følger:
import java.lang.reflect .*;

public class constructor2 {
offentlig constructor2 () {
}

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

public static void main (String args []) {
try {
Klasse CLS = Class.forName ("constructor2");
Klasse partypes [] = new Klasse [2];
partypes [0] = Integer.TYPE;
partypes [1] = Integer.TYPE;
Constructor 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 (Kan kastes e) {
System.err.println (e);
}
}
}

Ifølge den angitte parameter typen til å finne passende konstruktør og kjøre det til å opprette et nytt objekt forekomst.Denne metoden kan brukes under kjøring som dynamisk oppretter objektet, stedet for å opprette objekter under kompilering, noe som er svært verdifullt.


8. Endre feltet (felt)-verdien

Det er også en nyttig refleksjon av objektet er å endre verdien datafeltet.refleksjon fra et kjørende program for å finne objekter med navn i feltet og endre det, følgende eksempel for å illustrere dette poenget:
import java.lang.reflect .*;

public class field2 {
offentlige dobbel d;

public static void main (String args []) {
try {
Klasse CLS = Class.forName ("field2");
Field Fld = cls.getField ("d");
field2 f2obj = ny field2 ();
System.out.println ("d =" + f2obj.d);
fld.setDouble (f2obj, 12.34);
System.out.println ("d =" + f2obj.d);
} Catch (Kan kastes e) {
System.err.println (e);
}
}
}

Dette eksemplet, er feltets verdien endres av d 12.34.


9. Bruk av arrays

Denne artikkelen beskriver refleksjonen av den endelige operasjonen er å skape en rekke bruk.Array i Java-språket er en spesiell klasse type, kan en matrise referanse tildeles Object referanse.Se på følgende eksempel for å se hvordan arbeidet i matrisen:
import java.lang.reflect .*;

public class matrise1 {
public static void main (String args []) {
try {
Klasse CLS = Class.forName ("java.lang.String");
Objekt arr = Array.newInstance (CLS, 10);
Array.set (arr, 5, "dette er en test");
String s = (String) Array.get (arr, 5);
System.out.println (s);
} Catch (Kan kastes e) {
System.err.println (e);
}
}
}

Tilfeller av 10 enheter for å skape en String utvalg av lengde, for de første 5 posisjonene i strengen tildelt en verdi, og endelig få strengen fra tabellen og skrive det ut.

Følgende kode gir en mer kompleks eksempel:
import java.lang.reflect .*;

public class matrise2 {
public static void main (String args []) {
int dims [] = new int [] {5, 10, 15};
Objekt arr = Array.newInstance (Integer.TYPE, dims);
Objekt arrobj = Array.get (arr, 3);
Klasse 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]);
}
}

Eksempel skaper en 5 x 10 x 15 heltall array, og i [3] [5] [10] tilordnet en verdi på 37 elementer.Merk at flerdimensjonale arrays er faktisk matriser med matriser, for eksempel, etter den første Array.get, er arrobj en 10 x 15 matrise.Så får ett av elementene, dvs. en rekke av lengde 15, og bruke Array.setInt for sin første 10 elementene i oppdraget.

Merk at når du oppretter array-type er dynamisk, ved kompilering kjenner ikke til sin type.