Volajte metódy za behu pomocou Java Reflection

1. Prehľad

V tomto krátkom článku sa rýchlo pozrieme na to, ako na to vyvolať metódy za behu pomocou Java Reflection API.

2. Príprava

Vytvorme jednoduchú triedu, ktorú použijeme v nasledujúcich príkladoch:

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? a: b; }}

3. Získanie a Metóda Objekt

Najprv musíme získať Metóda objekt, ktorý odráža metódu, ktorú chceme vyvolať. The Trieda objekt, ktorý predstavuje typ, v ktorom je metóda definovaná, poskytuje dva spôsoby, ako to urobiť.

3.1. getMethod ()

Môžeme použiť getMethod () nájsť ľubovoľnú verejnú metódu, či už statickú alebo inštanciu definovanú v triede alebo v ktorejkoľvek z jej nadtried.

Ako prvý argument dostane názov metódy a za ňou nasledujú typy argumentov metódy:

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

3.2. getDeclaredMethod ()

Môžeme použiť getDeclaredMethod () získať akúkoľvek metódu definovanú v triede. Patria sem verejné, chránené, predvolené prístupy a dokonca aj súkromné ​​metódy, ale vylučujú sa metódy zdedené.

Prijíma rovnaké parametre ako getMethod ():

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

4. Vyvolanie metód

Vďaka Metóda napríklad na mieste, teraz môžeme zavolať vzývať() vykonať základnú metódu a získať vrátený objekt.

4.1. Metódy inštancie

Ak chcete vyvolať inštančnú metódu, prvý argument je vzývať() musí byť inštanciou Metóda , ktorá odráža vyvolanú metódu:

@Test public void givenObject_whenInvokePublicMethod_thenCorrect () {Metóda sumInstanceMethod = Operations.class.getMethod ("publicSum", int.class, double.class); Operácie operationsInstance = new Operations (); Dvojitý výsledok = (Double) sumInstanceMethod.invoke (operationsInstance, 1, 3); assertThat (result, equalTo (4.0)); }

4.2. Statické metódy

Pretože tieto metódy nevyžadujú volanie inštancie, môžeme prejsť nulový ako prvý argument:

@Test public void givenObject_whenInvokeStaticMethod_thenCorrect () {Metóda multiplyStaticMethod = Operations.class.getDeclaredMethod ("publicStaticMultiply", float.class, long.class); Dvojitý výsledok = (Double) multiplyStaticMethod.invoke (null, 3.5f, 2); assertThat (result, equalTo (7.0)); }

5. Prístupnosť metódy

V predvolenom nastavení nie sú všetky použité metódy prístupný. To znamená, že JVM pri ich vyvolaní vynucuje kontroly kontroly prístupu.

Napríklad, ak sa pokúsime zavolať súkromnú metódu mimo jej definujúcej triedy alebo chránenú metódu z vonkajšej strany podtriedy alebo balíka jej triedy, dostaneme IllegalAccessException:

@Test (očakáva sa = IllegalAccessException.class) public void givenObject_whenInvokePrivateMethod_thenFail () {Method andPrivateMethod = Operations.class.getDeclaredMethod ("privateAnd", boolean.class, boolean.class); Operácie operationsInstance = new Operations (); Boolean result = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (výsledok); } @Test (očakáva sa = IllegalAccessException.class) public void givenObject_whenInvokeProtectedMethod_thenFail () {metóda maxProtectedMethod = Operations.class.getDeclaredMethod ("protectedMax", int.class, int.class); Operácie operationsInstance = new Operations (); Výsledok celého čísla = (celé číslo) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (result, equalTo (4)); }

Volaním setAccesible (true) na objekte zrkadlenej metódy JVM potláča kontroly riadenia prístupu a umožňuje nám vyvolať metódu bez zrušenia výnimky:

@Test public void givenObject_whenInvokePrivateMethod_thenCorrect () {// ... andPrivateMethod.setAccessible (true); // ... Boolean result = (Boolean) andPrivateMethod.invoke (operationsInstance, true, false); assertFalse (výsledok); } @Test public void givenObject_whenInvokeProtectedMethod_thenCorrect () {// ... maxProtectedMethod.setAccessible (true); // ... Výsledok celého čísla = (Celé číslo) maxProtectedMethod.invoke (operationsInstance, 2, 4); assertThat (result, equalTo (4)); }

6. Záver

V tomto rýchlom článku sme videli, ako volať inštančné a statické metódy triedy za behu pomocou reflexie. Ukázali sme tiež, ako zmeniť prístupný príznak na objektoch odrazenej metódy, aby sa pri vyvolaní súkromných a chránených metód potlačili kontroly kontroly prístupu Java.

Ako vždy, ukážkový kód nájdete na Githube.


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