通过反射获取及调⽤⽅法(Method)
1、获取⽅法
使⽤反射获取某⼀个类中的⽅法,步骤:
①到获取⽅法所在类的字节码对象
②到需要被获取的⽅法
Class类中常⽤⽅法:
public Method[] getMethods():获取包括⾃⾝和继承过来的所有的public⽅法
public Method[] getDeclaredMethods():获取⾃⾝所有的⽅法(不包括继承的,和访问权限⽆关)
public Method getMethod(String methodName,Class<?>...parameterTypes):
表⽰调⽤指定的⼀个公共的⽅法(包括继承的)
参数:
methodName: 表⽰被调⽤⽅法的名字
parameterTypes:表⽰被调⽤⽅法的参数的Class类型如String.class
只有通过⽅法签名才能到唯⼀的⽅法,⽅法签名=⽅法名+参数列表(参数类型、参数个数、参数顺序)。
public Method getDeclaredMethod(String name,
Class<?>... parameterTypes):表⽰调⽤指定的⼀个本类中的⽅法(不包括继承的)
参数:
methodName: 表⽰被调⽤⽅法的名字
parameterTypes:表⽰被调⽤⽅法的参数的Class类型如String.class
总结:
四个⽅法中,不带Declared的⽅法能获取⾃⾝类和⽗类的所有public⽅法。带Declared的⽅法能获取⾃⾝所有⽅法但不能获取⽗类中的⽅法。只有通过⽅法签名才能到唯⼀的⽅法,⽅法签名=⽅法名+参数
列表(参数类型、参数个数、参数顺序)。
只能获取⽗类中的public⽅法,⽆法获取到⽗类的默认权限和private权限⽅法。
测试代码如下:
class P{
public void t1(){}
void t2(){}
private void t3(){}
}
class People extends P{
public void sayHi() {
System.out.println("sayHi()");
}
public void sayHello(String name) {
System.out.println("sayHello(String name) " + "name = " + name);
}
private void sayGoodBye(String name, int age) {
System.out.println("sayGoodBye(String name, int age) " + "name = " + name + " age = " + age);
}
}
public class MethodDemo {
public static void main(String[] args) throws Exception {
Class clazz = People.class;
/
/获取类⾃⾝及⽗类所有public⽅法
Method ms[] = Methods();
for (Method m : ms) {
System.out.println(m);
}
System.out.println("---------------------------");
//获取类⾃⾝所有⽅法(不会获取⽗类⽅法)
ms = DeclaredMethods();
for (Method m : ms) {
System.out.println(m);
}
System.out.println("---------------------------");
//只能获取⽗类中的public⽅法,⽆法获取到⽗类的默认权限和private权限⽅法
Method m = Method("t1", null);//public flex.P.t1()
System.out.println(m);
// m = Method("t2", null);//Exception in thread "main" java.lang.NoSuchMethodException: flex.People.t2()
// m = Method("t3", null);//Exception in thread "main" java.lang.NoSuchMethodException: flex.People.t3()
m = Method("sayHello", String.class);
System.out.println(m);
//Exception in thread "main" java.lang.NoSuchMethodException: flex.People.sayGoodBye(java.lang.String, int)
/
/getMethod⽅法只能获取public的
// m = Method("sayGoodBye", String.class,int.class);
// System.out.println(m);
m = DeclaredMethod("sayGoodBye", String.class,int.class);
System.out.println(m);
//带Declared的⽆法获取⽗类中的⽅法
// m = DeclaredMethod("t1", null);//Exception in thread "main" java.lang.flex.People.t1()
// System.out.println(m);
}
}
2、调⽤⽅法
使⽤反射调⽤⽅法步骤:
①到被调⽤⽅法所在的字节码
②获取到被调⽤的⽅法对象
③调⽤该⽅法
如何使⽤反射调⽤⼀个⽅法:
在Method类中有⽅法:
public Object invoke(Object args):表⽰调⽤当前Method所表⽰的⽅法
参数:
obj: 表⽰被调⽤⽅法底层所属对象
Method m = Method("sayHi",String.class);
args:表⽰调⽤⽅法是传递的实际参数
返回:
底层⽅法的返回结果
obj: 表⽰被调⽤⽅法底层所属对象举例说明如下:
class Test {
public String sayHi(String name) {
System.out.println("sayHi()......." + name);
return "XXX";
}
}
sayHi的底层所属对象就是Test的对象:以前调⽤⽅法:
Test e = new Test();
String ret = e.sayHi("huangweiyong");
调⽤私有⽅法(切记):
在调⽤私有⽅法之前:应该设置该⽅法为可访问的
⼜因为Method是AccessibleObject⼦类,所以Method中具有该⽅法.
sayGoodByeMethod.setAccessible(true);
3、调⽤静态⽅法和可变参数⽅法
使⽤反射调⽤静态⽅法:
public Object invoke(Object args);
如果底层⽅法是静态的,那么可以忽略指定的 obj参数。将obj参数设置为null即可。
使⽤反射调⽤可变参数的⽅法:
对于数组类型的引⽤类型的参数,底层会⾃动解包,为了解决该问题,我们使⽤Object的⼀维数组把实际参数包装起来.
(牢记)以后使⽤反射调⽤invoke⽅法,在传递实际参数的时候,⽆论是基本数据类型还是引⽤数据类型,也⽆论是可变参数类型,反正就是⼀切实际参数都包装在newObject[]{}中,就没问题。
m.invoke(⽅法底层所属对象,newObject[]{实际参数});通⽤
下⾯写个例⼦加强理解:
java反射获取父类属性public class VarArgsMethodDemo {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("flex.VarArgsMethodDemo");
Method m = Method("sum", int[].class);
// m.invoke(null, 1,2,3,4);//error
m.invoke(null, new int[]{1,2,3});//yes
m.invoke(null, new Object[]{new int[]{1,3,4}});//yes
System.out.println("---------------------------");
m = Method("toStr", String[].class);
// m.invoke(null, "A","q","cc");//error
// m.invoke(null, new String[]{"A","q","cc"});//error 引⽤类型和基本数据类型的区别,基本数据类型可以直接使⽤,这⾥会⾃动解包,我们需要⼿动包装⼀层// 对于数组类型的引⽤类型的参数,底层会⾃动解包,为了解决该问题,我们使⽤Object的⼀维数组把实际参数包装起来.
//new Object[]{new String[]{"huang ","weiyong"," 18"}} 解包成new String[]{"huang ","weiyong"," 18"}
m.invoke(null, new Object[]{new String[]{"huang ","weiyong"," 18"}});
}
//可变参数底层就是数组
//基本数据类型
public static int sum(int ...args) {
int sum = 0;
for (int i : args) {
sum+=i;
}
System.out.println(sum);
return sum;
}
//引⽤数据类型
public static void toStr(String ...args) {
System.out.String(args));
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论