Metode Panggilan pada Waktu Proses Menggunakan Java Reflection

1. Ikhtisar

Dalam artikel singkat ini, kita akan melihat sekilas cara memanggil metode pada waktu proses menggunakan Java Reflection API .

2. Bersiap

Mari buat kelas sederhana yang akan kita gunakan untuk contoh berikut:

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. Memperoleh Objek Metode

Pertama, kita perlu mendapatkan objek Metode yang mencerminkan metode yang ingin kita panggil. The Kelas objek, mewakili jenis di mana metode ini didefinisikan, menyediakan dua cara untuk melakukan hal ini.

3.1. getMethod ()

Kita bisa menggunakan getMethod () untuk menemukan metode publik apa pun, baik itu statis atau instance yang didefinisikan di kelas atau superkelasnya.

Ini menerima nama metode sebagai argumen pertama, diikuti dengan jenis argumen metode:

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

3.2. getDeclaredMethod ()

Kita bisa menggunakan getDeclaredMethod () untuk mendapatkan metode apa pun yang ditentukan di kelas. Ini termasuk metode publik, dilindungi, default, dan bahkan privat tetapi tidak termasuk metode yang diwariskan.

Ini menerima parameter yang sama seperti getMethod () :

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

4. Memohon Metode

Dengan instance Metode di tempat, sekarang kita bisa memanggil invoke () untuk mengeksekusi metode yang mendasarinya dan mendapatkan objek yang dikembalikan.

4.1. Metode Instance

Untuk memanggil metode instance, argumen pertama ke invoke () harus berupa instance Metode yang mencerminkan metode yang sedang dipanggil:

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

4.2. Metode Statis

Karena metode ini tidak memerlukan instance untuk dipanggil, kita dapat mengirimkan null sebagai argumen pertama:

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

5. Aksesibilitas Metode

Secara default, tidak semua metode yang direfleksikan dapat diakses . Ini berarti JVM memberlakukan pemeriksaan kontrol akses saat menjalankannya.

Misalnya, jika kita mencoba memanggil metode privat di luar kelas yang menentukan atau metode yang dilindungi dari luar subkelas atau paket kelasnya, kita akan mendapatkan IllegalAccessException :

@Test(expected = IllegalAccessException.class) public void 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(result); } @Test(expected = IllegalAccessException.class) public void givenObject_whenInvokeProtectedMethod_thenFail() { Method maxProtectedMethod = Operations.class.getDeclaredMethod( "protectedMax", int.class, int.class); Operations operationsInstance = new Operations(); Integer result = (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4); assertThat(result, equalTo(4)); }

Dengan memanggil setAccesible (true) pada objek metode yang direfleksikan, JVM menahan pemeriksaan kontrol akses dan memungkinkan kita untuk memanggil metode tanpa mengeluarkan pengecualian:

@Test public void givenObject_whenInvokePrivateMethod_thenCorrect() { // ... andPrivateMethod.setAccessible(true); // ... Boolean result = (Boolean) andPrivateMethod.invoke(operationsInstance, true, false); assertFalse(result); } @Test public void givenObject_whenInvokeProtectedMethod_thenCorrect() { // ... maxProtectedMethod.setAccessible(true); // ... Integer result = (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4); assertThat(result, equalTo(4)); }

6. Kesimpulan

Dalam artikel singkat ini, kita telah melihat cara memanggil instance dan metode statis kelas saat runtime melalui refleksi. Kami juga menunjukkan cara mengubah flag yang dapat diakses pada objek metode yang direfleksikan untuk menekan pemeriksaan kontrol akses Java saat memanggil metode privat dan dilindungi.

Seperti biasa, kode contoh dapat ditemukan di Github.