Methoden tijdens runtime aanroepen met behulp van Java Reflection

1. Overzicht

In dit korte artikel zullen we in het kort bekijken hoe u dat kunt doen roep methoden aan tijdens runtime met behulp van de Java Reflection API.

2. Voorbereiding

Laten we een eenvoudige klasse maken die we zullen gebruiken voor de volgende voorbeelden:

public class Operations {public double publicSum (int a, double b) {return a + b; } public static double publicStaticMultiply (float a, long b) {return a * b; } private boolean privateAnd (boolean a, boolean b) {return a && b; } protected int protectedMax (int a, int b) {return a> b? een: b; }}

3. Verkrijgen van een Methode Voorwerp

Eerst moeten we een Methode object dat de methode weerspiegelt die we willen aanroepen. De Klasse object, dat het type vertegenwoordigt waarin de methode is gedefinieerd, biedt twee manieren om dit te doen.

3.1. getMethod ()

We kunnen gebruiken getMethod () om een ​​openbare methode te vinden, of het nu een statische methode is of een instantie die is gedefinieerd in de klasse of een van zijn superklassen.

Het ontvangt de naam van de methode als het eerste argument, gevolgd door de typen argumenten van de methode:

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

3.2. getDeclaredMethod ()

We kunnen gebruiken getDeclaredMethod () om een ​​methode te krijgen die in de klasse is gedefinieerd. Dit omvat openbare, beveiligde, standaardtoegang en zelfs privémethoden, maar niet geërfde methoden.

Het ontvangt dezelfde parameters als getMethod ():

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

4. Aanroepen van methoden

Met de Methode bijvoorbeeld op zijn plaats, kunnen we nu bellen beroep doen op() om de onderliggende methode uit te voeren en het geretourneerde object op te halen.

4.1. Instantiemethoden

Om een ​​instantiemethode aan te roepen, moet het eerste argument to beroep doen op() moet een instantie zijn van Methode dat weerspiegelt de methode die wordt aangeroepen:

@Test openbare leegte gegevenObject_whenInvokePublicMethod_thenCorrect () {Methode sumInstanceMethod = Operations.class.getMethod ("publicSum", int.class, double.class); Operations operationsInstance = nieuwe Operations (); Dubbel resultaat = (Dubbel) sumInstanceMethod.invoke (operationsInstance, 1, 3); assertThat (resultaat, gelijk aan (4.0)); }

4.2. Statische methoden

Omdat voor deze methoden geen instantie nodig is om te worden aangeroepen, kunnen we doorgeven nul als eerste argument:

@Test openbare leegte gegevenObject_whenInvokeStaticMethod_thenCorrect () {Method multiplyStaticMethod = Operations.class.getDeclaredMethod ("publicStaticMultiply", float.class, long.class); Dubbel resultaat = (dubbel) multiplyStaticMethod.invoke (null, 3.5f, 2); assertThat (resultaat, gelijk aan (7.0)); }

5. Methode Toegankelijkheid

Standaard zijn niet alle weergegeven methoden beschikbaar. Dit betekent dat de JVM toegangscontroles afdwingt bij het aanroepen ervan.

Als we bijvoorbeeld een privémethode proberen aan te roepen buiten de definiërende klasse of een beschermde methode van buiten een subklasse of het bijbehorende klassepakket, krijgen we een IllegalAccessException:

@Test (verwacht = IllegalAccessException.class) public void givenObject_whenInvokePrivateMethod_thenFail () {Method andPrivateMethod = Operations.class.getDeclaredMethod ("privateAnd", boolean.class, boolean.class); Operations operationsInstance = nieuwe Operations (); Booleaans resultaat = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (resultaat); } @Test (verwacht = IllegalAccessException.class) public void givenObject_whenInvokeProtectedMethod_thenFail () {Method maxProtectedMethod = Operations.class.getDeclaredMethod ("protectedMax", int.class, int.class); Operations operationsInstance = nieuwe Operations (); Integer resultaat = (Geheel getal) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (resultaat, gelijk aan (4)); }

Door te bellen setAccesible (true) op een gereflecteerd methodeobject onderdrukt de JVM de toegangscontrolecontroles en stelt ons in staat om de methode aan te roepen zonder een uitzondering op te werpen:

@Test openbare leegte gegevenObject_whenInvokePrivateMethod_thenCorrect () {// ... andPrivateMethod.setAccessible (true); // ... Booleaans resultaat = (Booleaans) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (resultaat); } @Test openbare leegte gegevenObject_whenInvokeProtectedMethod_thenCorrect () {// ... maxProtectedMethod.setAccessible (true); // ... Integer resultaat = (Geheel getal) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (resultaat, gelijk aan (4)); }

6. Conclusie

In dit korte artikel hebben we gezien hoe we door middel van reflectie instantie en statische methoden van een klasse tijdens runtime kunnen aanroepen. We hebben ook laten zien hoe de toegankelijkheidsvlag op de gereflecteerde methodeobjecten kan worden gewijzigd om Java-toegangscontrolecontroles te onderdrukken bij het aanroepen van privé- en beschermde methoden.

Zoals altijd is de voorbeeldcode te vinden op Github.