在运行时使用Java反射调用方法
最后修改:2019年9月8日
1.概述
在这篇简短的文章中,我们将快速了解如何在运行时使用Java反射API调用方法。
2.准备
让我们创建一个简单的类,用于下面的示例:
public class Operations {public double public sum (int a, double b) {return a + b;} public static double publicStaticMultiply(float a, long b) {return a * b;} private boolean private and (boolean a, boolean b) {return a && b;} protected int protectedMax(int a, int b) {return a > b ?a: b;}}
3.获得方法对象
首先,我们需要一个方法对象,反映我们想要调用的方法。的类对象表示定义方法的类型,它提供了两种实现方法。
3.1。getMethod ()
我们可以用getMethod ()要查找任何公共方法,请静态或实例在类或其任何超类中定义。
它接收方法名作为第一个参数,然后是方法参数的类型:
方法sumInstanceMethod = Operations.class。getMethod(“publicSum”,int.class double.class);方法multiplyStaticMethod = Operations.class。getMethod("publicStaticMultiply", float.class, long.class);
3.2。getdeclaredmethod()
我们可以用getdeclaredmethod()获取类中定义的任何方法。这包括公共的、受保护的、默认的访问,甚至私有的方法,但不包括继承的方法。
它接收的参数与getMethod ():
方法andprivatemethod = Operations.Class.getDeclaredMethod(“privateand”,boolean.class,boolean.class);
方法maxProtectedMethod = Operations.class。getDeclaredMethod(“protectedMax”,int.class int.class);
4.调用方法
与方法实例就绪后,我们现在可以调用invoke ()执行底层方法并获取返回的对象。
4.1。实例方法
要调用实例方法,第一个参数为invoke ()必须是一个实例方法这反映了正在调用的方法:
@Test public void givenobject_wheninvokepublicmethod_thcorrect () {Method sumInstanceMethod = Operations.class. class. ();getMethod(“publicSum”,int.class double.class);operationsInstance = new Operations();Double result = (Double) sumInstanceMethod。调用(operationsInstance, 1, 3);为了(因此,等于(4.0));}
4.2。静态方法
由于这些方法不需要调用实例,因此我们可以通过零作为第一个参数:
@test public voidedobject_wheninvokestaticmethod_thengorrect(){method multiplystoctmethod = Operations.Class.getDeclaredMethod(“PublicStaticMultiply”,float.class,long.class);双重结果=(双)多重rstaticmethod.invoke(null,3.5f,2);assertthat(结果,等于(7.0));}
5.方法的可访问性
默认情况下,并不是所有反射的方法都是这样可访问的。这意味着JVM在调用它们时强制执行访问控制检查。
例如,如果我们试图在定义类之外调用私有方法,或者在子类或其类的包之外调用受保护方法,我们将得到一个IllegalAccessException:
@Test(expected = IllegalAccessException.class) public void givenObject_whenInvokePrivateMethod_thenFail(){方法和privatemethod = Operations.class。getDeclaredMethod("privateAnd", boolean.class, boolean.class);operationsInstance = new Operations();Boolean result = (Boolean) andPrivateMethod。调用(operationsInstance,真、假);assertFalse(结果);} @Test(expected = illegalaccessexeption .class) public void givenObject_whenInvokeProtectedMethod_thenFail(){方法maxProtectedMethod = Operations.class. class. class);getDeclaredMethod("protectedMax", int.class, int.class);operationsInstance = new Operations();Integer result = (Integer) maxProtectedMethod。调用(operationsInstance、2、4);为了(因此,等于(4));}
通过调用etapcesible(true)在反射的方法对象上,JVM抑制访问控制检查并允许我们在不抛出异常的情况下调用该方法:
@Test public void givenobject_wheninvokeprivatemethod_thcorrect(){//…andPrivateMethod.setAccessible(真正的);/ /……Boolean result = (Boolean) andPrivateMethod。调用(operationsInstance,真、假);assertFalse(结果);} @Test public void givenobject_wheninvokeprotectedmethod_thcorrect(){//…maxProtectedMethod.setAccessible(真正的);/ /……Integer result = (Integer) maxProtectedMethod。调用(operationsInstance、2、4);为了(因此,等于(4)); }
6.结论
在这篇快速文章中,我们看到了如何通过反射在运行时调用类的实例方法和静态方法。我们还展示了如何更改反射的方法对象上的accessible标志,以便在调用私有和受保护的方法时取消Java访问控制检查。
与往常一样,可以找到示例代码在Github。