Metode poziva tijekom izvođenja koristeći Java Reflection

1. Pregled

U ovom ćemo kratkom članku na brzinu pogledati kako to učiniti pozvati metode tijekom izvođenja pomoću API-ja Java Reflection.

2. Priprema

Stvorimo jednostavnu klasu koju ćemo koristiti za primjere koji slijede:

javne klase Operacije {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? a: b; }}

3. Dobivanje a Metoda Objekt

Prvo, moramo dobiti a Metoda objekt koji odražava metodu koju želimo prizvati. The Razred Objekt, koji predstavlja tip u kojem je metoda definirana, pruža dva načina za to.

3.1. getMethod ()

Možemo koristiti getMethod () kako bi se pronašla bilo koja javna metoda, bila ona statična ili instanca koja je definirana u klasi ili bilo kojoj od njezinih superklasa.

Prima naziv metode kao prvi argument, a slijede vrste argumenata metode:

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

3.2. getDeclaredMethod ()

Možemo koristiti getDeclaredMethod () kako bi se dobila bilo koja metoda definirana u klasi. To uključuje javne, zaštićene, zadane pristupe, pa čak i privatne metode, ali isključuje naslijeđene.

Prima iste parametre kao i getMethod ():

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

4. Pozivanje metoda

Uz Metoda primjer na mjestu, sada možemo nazvati prizvati () za izvršavanje osnovne metode i dobivanje vraćenog objekta.

4.1. Instance metode

Da biste pozvali metodu instance, prvi argument za prizvati () mora biti primjerak Metoda koja odražava metodu koja se poziva:

@Test javna praznina givenObject_whenInvokePublicMethod_thenCorrect () {Metoda sumInstanceMethod = Operations.class.getMethod ("publicSum", int.class, double.class); Operations OperationsInstance = new Operations (); Dvostruki rezultat = (Dvostruki) sumInstanceMethod.invoke (operationsInstance, 1, 3); assertThat (rezultat, jednakTo (4.0)); }

4.2. Statičke metode

Budući da ove metode ne zahtijevaju pozivanje instance, možemo proći null kao prvi argument:

@Test javna praznina givenObject_whenInvokeStaticMethod_thenCorrect () {Metoda multiplyStaticMethod = Operations.class.getDeclaredMethod ("publicStaticMultiply", float.class, long.class); Dvostruki rezultat = (Dvostruko) multiplyStaticMethod.invoke (null, 3.5f, 2); assertThat (rezultat, jednakTo (7.0)); }

5. Dostupnost metode

Prema zadanim postavkama nisu sve reflektirane metode dostupan. To znači da JVM provodi provjere kontrole pristupa kada ih poziva.

Na primjer, ako pokušamo pozvati privatnu metodu izvan njezine definirajuće klase ili zaštićenu metodu izvan podklase ili paketa njene klase, dobit ćemo IllegalAccessException:

@Test (očekuje se = IllegalAccessException.class) javna praznina givenObject_whenInvokePrivateMethod_thenFail () {Method andPrivateMethod = Operations.class.getDeclaredMethod ("privateAnd", boolean.class, boolean.class); Operations OperationsInstance = new Operations (); Logički rezultat = (logički) iPrivateMethod.invoke (operationsInstance, true, false); assertFalse (rezultat); } @Test (očekuje se = IllegalAccessException.class) javna praznina givenObject_whenInvokeProtectedMethod_thenFail () {Metoda maxProtectedMethod = Operations.class.getDeclaredMethod ("protectedMax", int.class, int.class); Operations OperationsInstance = new Operations (); Integer rezultat = (Integer) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (rezultat, jednakTo (4)); }

Pozivanjem setAccesible (true) na reflektiranom objektu metode, JVM potiskuje provjere kontrole pristupa i omogućuje nam pozivanje metode bez izbacivanja iznimke:

@Test javna praznina givenObject_whenInvokePrivateMethod_thenCorrect () {// ... andPrivateMethod.setAccessible (true); // ... logički rezultat = (logički) iPrivateMethod.invoke (operationsInstance, true, false); assertFalse (rezultat); } @Test javna praznina givenObject_whenInvokeProtectedMethod_thenCorrect () {// ... maxProtectedMethod.setAccessible (true); // ... Integer rezultat = (Integer) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (rezultat, jednakTo (4)); }

6. Zaključak

U ovom kratkom članku vidjeli smo kako putem refleksije pozvati instance i statičke metode klase u vrijeme izvođenja. Također smo pokazali kako promijeniti dostupnu zastavicu na reflektiranim objektima metode kako bi se potisnule provjere Java kontrole pristupa prilikom pozivanja privatnih i zaštićenih metoda.

Kao i uvijek, primjer koda možete pronaći na Githubu.