Kaedah Panggil di Runtime Menggunakan Refleksi Java

1. Gambaran keseluruhan

Dalam artikel pendek ini, kita akan melihat dengan cepat bagaimana menggunakan kaedah pada waktu runtime menggunakan Java Reflection API .

2. Bersedia

Mari buat kelas sederhana yang akan kami 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 Kaedah

Pertama, kita perlu mendapatkan objek Kaedah yang mencerminkan kaedah yang ingin kita gunakan. The Kelas objek, yang mewakili jenis di mana kaedah yang ditetapkan, menyediakan dua cara untuk melakukan ini.

3.1. getMetode ()

Kami dapat menggunakan getMethod () untuk mencari kaedah umum, baik itu statik atau contoh yang ditentukan dalam kelas atau mana-mana kacamata supernya .

Ia menerima nama kaedah sebagai argumen pertama, diikuti oleh jenis argumen kaedah:

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

3.2. getDeclaredMethod ()

Kita boleh menggunakan getDeclaredMethod () untuk mendapatkan kaedah yang ditentukan dalam kelas. Ini merangkumi kaedah awam, dilindungi, akses lalai, dan juga kaedah peribadi tetapi tidak termasuk kaedah yang diwarisi.

Ia menerima parameter yang sama dengan getMethod () :

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

4. Kaedah Memohon

Dengan Menghubungi contoh di tempat, kita kini boleh menghubungi sembah () untuk melaksanakan kaedah yang mendasari dan mendapatkan objek yang dikembalikan.

4.1. Kaedah Contoh

Untuk menggunakan kaedah instance, argumen pertama untuk memanggil () mestilah contoh Kaedah yang mencerminkan kaedah yang 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. Kaedah Statik

Oleh kerana kaedah ini tidak memerlukan contoh dipanggil, kita dapat menjadikan nol 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. Kebolehcapaian Kaedah

Secara lalai, tidak semua kaedah yang dicerminkan dapat diakses . Ini bermaksud bahawa JVM menegakkan pemeriksaan kawalan akses ketika memintanya.

Sebagai contoh, jika kita cuba memanggil kaedah peribadi di luar kelas penentu atau kaedah yang dilindungi dari luar subkelas atau pakej kelasnya, kita akan mendapat 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 (benar) pada objek kaedah yang dipantulkan, JVM menekan pemeriksaan kawalan akses dan membolehkan kita menggunakan kaedah tersebut tanpa membuang 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. Kesimpulannya

Dalam artikel ringkas ini, kita telah melihat cara memanggil kaedah contoh dan statik kelas pada waktu berjalan melalui refleksi. Kami juga menunjukkan cara mengubah bendera yang dapat diakses pada objek metode yang dipantulkan untuk menekan pemeriksaan kendali akses Java ketika menggunakan metode pribadi dan dilindungi.

Seperti biasa, kod contoh boleh didapati di Github.