Opkaldsmetoder ved kørsel ved hjælp af Java-refleksion

1. Oversigt

I denne korte artikel tager vi et hurtigt kig på, hvordan man gør det påkalde metoder ved kørsel ved hjælp af Java Reflection API.

2. Gør dig klar

Lad os oprette en enkel klasse, som vi bruger til de følgende eksempler:

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

3. Opnåelse af en Metode Objekt

Først skal vi få en Metode objekt, der afspejler den metode, vi vil påberåbe. Det Klasse objekt, der repræsenterer den type, hvor metoden er defineret, giver to måder at gøre dette på.

3.1. getMethod ()

Vi kan bruge getMethod () at finde en hvilken som helst offentlig metode, det være sig statisk eller forekomst, der er defineret i klassen eller nogen af ​​dens superklasser.

Det modtager metodens navn som det første argument efterfulgt af typerne af metodens argumenter:

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

3.2. getDeclaredMethod ()

Vi kan bruge getDeclaredMethod () for at få en hvilken som helst metode defineret i klassen. Dette inkluderer offentlig, beskyttet, standardadgang og endda private metoder, men ekskluderer nedarvede.

Den modtager de samme parametre som getMethod ():

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

4. Påkaldsmetoder

Med Metode eksempel på plads, kan vi nu ringe påberåbe sig () for at udføre den underliggende metode og få det returnerede objekt.

4.1. Instansmetoder

At påberåbe sig en instansmetode, det første argument til påberåbe sig () skal være en forekomst af Metode der afspejler den metode, der påberåbes:

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

4.2. Statiske metoder

Da disse metoder ikke kræver, at der kaldes en instans, kan vi passere nul som det første argument:

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

5. Metode tilgængelighed

Som standard er ikke alle reflekterede metoder det tilgængelig. Dette betyder, at JVM håndhæver adgangskontrolkontroller, når de påberåber dem.

For eksempel, hvis vi forsøger at kalde en privat metode uden for dens definerende klasse eller en beskyttet metode uden for en underklasse eller dens klassepakke, får vi en Ulovlig adgangsundtagelse:

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

Ved at ringe setAccessible (true) på et reflekteret metodeobjekt undertrykker JVM adgangskontrolcheckene og giver os mulighed for at påberåbe sig metoden uden at kaste en undtagelse:

@Test offentligt ugyldigt givenObject_whenInvokePrivateMethod_thenCorrect () {// ... andPrivateMethod.setAccessible (true); // ... Boolean result = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (resultat); } @ Test offentligt ugyldigt givenObject_whenInvokeProtectedMethod_thenCorrect () {// ... maxProtectedMethod.setAccessible (true); // ... Heltalsresultat = (Heltals) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (resultat, equalTo (4)); }

6. Konklusion

I denne hurtige artikel har vi set, hvordan man kalder instans og statiske metoder til en klasse ved runtime gennem refleksion. Vi viste også, hvordan man ændrer det tilgængelige flag på de reflekterede metodeobjekter for at undertrykke Java-adgangskontrolkontrol, når man påberåber private og beskyttede metoder.

Som altid kan eksempelkoden findes på Github.