Anropsmetoder ved kjøretid ved hjelp av Java-refleksjon

1. Oversikt

I denne korte artikkelen tar vi en rask titt på hvordan du gjør det påkalle metoder ved kjøretid ved hjelp av Java Reflection API.

2. Gjør deg klar

La oss lage en enkel klasse som vi bruker for eksemplene som følger:

public class Operations {public double publicSum (int a, double b) {return a + b; } offentlig statisk dobbel publicStaticMultiply (float a, long b) {return a * b; } privat boolsk privatAnd (boolsk a, boolsk b) {return a && b; } beskyttet int protectedMax (int a, int b) {return a> b? a: b; }}

3. Få en Metode Gjenstand

Først må vi få en Metode objekt som gjenspeiler metoden vi vil påberope. De Klasse objektet, som representerer typen som metoden er definert i, gir to måter å gjøre dette på.

3.1. getMethod ()

Vi kan bruke getMethod () å finne en hvilken som helst offentlig metode, det være seg statisk eller forekomst som er definert i klassen eller noen av dens superklasser.

Den mottar metodens navn som det første argumentet, etterfulgt av typene av metodens argumenter:

Method sumInstanceMethod = Operations.class.getMethod ("publicSum", int.class, double.class); Method multiplyStaticMethod = Operations.class.getMethod ("publicStaticMultiply", float.class, long.class);

3.2. getDeclaredMethod ()

Vi kan bruke getDeclaredMethod () for å få definert hvilken som helst metode i klassen. Dette inkluderer offentlig, beskyttet, standard tilgang og til og med private metoder, men ekskluderer arvede.

Den mottar de samme parametrene som getMethod ():

Method andPrivateMethod = Operations.class.getDeclaredMethod ("privateAnd", boolean.class, boolean.class);
Metode maxProtectedMethod = Operations.class.getDeclaredMethod ("protectedMax", int.class, int.class);

4. Påkalle metoder

Med Metode eksempel på plass, kan vi nå ringe påkalle () for å utføre den underliggende metoden og få det returnerte objektet.

4.1. Instansmetoder

Å påkalle en instansemetode, det første argumentet til påkalle () må være en forekomst av Metode som gjenspeiler metoden som påberopes:

@Test public void givenObject_whenInvokePublicMethod_thenCorrect () {Method sumInstanceMethod = Operations.class.getMethod ("publicSum", int.class, double.class); Operations operationsInstance = new Operations (); Dobbelt resultat = (Dobbelt) sumInstanceMethod.invoke (operationsInstance, 1, 3); assertThat (resultat, equalTo (4.0)); }

4.2. Statiske metoder

Siden disse metodene ikke krever at en forekomst skal kalles, kan vi passere null som det første argumentet:

@Test public void givenObject_whenInvokeStaticMethod_thenCorrect () {Method multiplyStaticMethod = Operations.class.getDeclaredMethod ("publicStaticMultiply", float.class, long.class); Dobbelt resultat = (Dobbelt) multiplyStaticMethod.invoke (null, 3.5f, 2); assertThat (resultat, equalTo (7.0)); }

5. Metodtilgjengelighet

Som standard er ikke alle reflekterte metoder tilgjengelig. Dette betyr at JVM håndhever tilgangskontrollsjekker når de påkaller dem.

For eksempel, hvis vi prøver å kalle en privat metode utenfor den definerende klassen eller en beskyttet metode utenfor en underklasse eller klassens pakke, får vi en IllegalAccessException:

@Test (forventet = IllegalAccessException.class) offentlig ugyldig givenObject_whenInvokePrivateMethod_thenFail () {Method andPrivateMethod = Operations.class.getDeclaredMethod ("privateAnd", boolean.class, boolean.class); Operations operationsInstance = new Operations (); Boolean result = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (resultat); } @Test (forventet = IllegalAccessException.class) offentlig ugyldig givenObject_whenInvokeProtectedMethod_thenFail () {Method maxProtectedMethod = Operations.class.getDeclaredMethod ("protectedMax", int.class, int.class); OperasjonsoperasjonerInstans = nye operasjoner (); Heltalsresultat = (Heltall) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (resultat, equalTo (4)); }

Ved å ringe setAccessible (true) på et reflektert metodeobjekt, undertrykker JVM tilgangskontrollkontrollene og lar oss påkalle metoden uten å kaste et unntak:

@Test offentlig ugyldig gittObject_whenInvokePrivateMethod_thenCorrect () {// ... andPrivateMethod.setAccessible (true); // ... Boolean result = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (resultat); } @Test offentlig ugyldig gittObject_whenInvokeProtectedMethod_thenCorrect () {// ... maxProtectedMethod.setAccessible (true); // ... Heltallresultat = (Heltall) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (resultat, equalTo (4)); }

6. Konklusjon

I denne raske artikkelen har vi sett hvordan vi kan ringe instans og statiske metoder for en klasse ved kjøretid gjennom refleksjon. Vi viste også hvordan du endrer det tilgjengelige flagget på de reflekterte metodeobjektene for å undertrykke Java-kontrollkontroller når du påberoper private og beskyttede metoder.

Som alltid kan eksempelkoden finnes på Github.


$config[zx-auto] not found$config[zx-overlay] not found