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[] = clazz.getMethods();
for (Method m : ms) {
System.out.println(m);
}
System.out.println("---------------------------"); //获取类自身所有方法(不会获取父类方法)
ms = clazz.getDeclaredMethods();
for (Method m : ms) {
System.out.println(m);
}
System.out.println("---------------------------"); //只能获取父类中的public方法,无法获取到父类的默认权限和private权限方法
Method m = clazz.getMethod("t1", null);//public void com.reflex.P.t1()
System.out.println(m);
// m = clazz.getMethod("t2", null);//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.t2()
// m = clazz.getMethod("t3", null);//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.t3()
m = clazz.getMethod("sayHello", String.class);
System.out.println(m);
//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.sayGoodBye(java.lang.String, int) //getMethod方法只能获取public的
// m = clazz.getMethod("sayGoodBye", String.class,int.class);
// System.out.println(m);
m = clazz.getDeclaredMethod("sayGoodBye", String.class,int.class);
System.out.println(m);
//带Declared的无法获取父类中的方法
// m = clazz.getDeclaredMethod("t1", null);//Exception in thread "main" java.lang.NoSuchMethodException:com.reflex.People.t1()
// System.out.println(m);
}
}

2、调用方法
使用反射调用方法步骤:
①找到被调用方法所在的字节码
②获取到被调用的方法对象
③调用该方法

如何使用反射调用一个方法:
在Method类中有方法:

public Object invoke(Object obj,Object... args):表示调用当前Method所表示的方法

  参数:
obj: 表示被调用方法底层所属对象
Method m = clz.getMethod("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");

调用私有方法(切记):
在调用私有方法之前:应该设置该方法为可访问的
又因为MethodAccessibleObject子类,所以Method中具有该方法.
sayGoodByeMethod.setAccessible(true);

3、调用静态方法和可变参数方法
使用反射调用静态方法:
public Object invoke(Object obj,Object... args);
如果底层方法是静态的,那么可以忽略指定的 obj参数。将obj参数设置为null即可。

使用反射调用可变参数的方法:
对于数组类型的引用类型的参数,底层会自动解包,为了解决该问题,我们使用Object的一维数组把实际参数包装起来.

(牢记)以后使用反射调用invoke方法,在传递实际参数的时候,无论是基本数据类型还是引用数据类型,也无论是可变参数类型,反正就是一切实际参数都包装在newObject[]{}中,就没问题。


m.invoke(方法底层所属对象,newObject[]{实际参数});通用


下面写个例子加强理解:

public class VarArgsMethodDemo {

public static void main(String[] args) throws Exception {

    Class clazz = Class.forName("com.reflex.VarArgsMethodDemo");
Method m = clazz.getMethod("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 = clazz.getMethod("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.println(Arrays.toString(args));
}
}

通过反射获取及调用方法(Method)的更多相关文章

  1. C#通过反射获取上层调用方法信息

    System.Diagnostics.StackFrame frame = ); System.Reflection.MethodBase method = frame.GetMethod(); st ...

  2. 廖雪峰Java4反射与泛型-1反射-2访问字段Field和3调用方法Method

    2.字段Field 2.1.通过Class实例获取字段field信息: getField(name): 获取某个public的field,包括父类 getDeclaredField(name): 获取 ...

  3. tp 框架 利用反射实现对象调用方法

    <?php class Person{ public $name="xiaoming"; function say(){ echo "i am ".$th ...

  4. Java反射学习-3 - 反射获取属性,方法,构造器

    package cn.tx.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import ...

  5. php反射获取类和方法中的注释

    通过php中的反射机制,获取该类的文档注释,再通过获取其所有的方法,获取方法的注释 所用到的主要类及其方法 ReflectionClass ReflectionClass::getDocComment ...

  6. java 反射获取属性值 方法

    public static void main(String[] args) throws SecurityException, ClassNotFoundException, IllegalArgu ...

  7. java 通过反射获取调用类方法及属性

    首先说下反射是什么?反射是Sun公司推出的一组API,此组API位于Java.lang.reflect中 反射的作用是编写工具(例如eclipse),编写框架,当然对于一般的程序,我们不可能用反射来做 ...

  8. Android开发之通过反射获取到Android隐藏的方法

    在PackageManger中,有些方法被隐藏了,无法直接调用,需要使用反射来获取到该方法. 比如方法:getPackageSizeInfo(),通过这个方法可以获取到apk的CacheSize,Co ...

  9. [No000085]C#反射Demo,通过类名(String)创建类实例,通过方法名(String)调用方法

    using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Sy ...

随机推荐

  1. [修正] Firemonkey 中英文混排折行,省略字符,首字避开标点

    问题:FMX 在移动平台的文字显示并非由该平台的原生 API 来显示,而是由 FMX.TextLayout.GPU 来处理,也许是官方没留意到中文字符的问题,造成在中英文混排折行时,有些问题. 修正: ...

  2. java(一)IntelliJ和eclipse环境下的Hello World

    1. IntelliJ环境下的Hello World 1. 启动IntelliJ IDE,选择File->New->Project 选择Java如果没有出现Project SDK,则选择N ...

  3. 创建 ASP.NET Web API的Help Page

    转:创建WEBAPI项目 转:添加测试API中的ASP.NET Web API帮助页面

  4. Centos 固定ip

    vim /etc/sysconfig/network-scripts/ifcfg-eth0 BOOTPROTO="static" ONBOOT=yes IPADDR=192.168 ...

  5. GridControl中文属性

    1   Appearance EmbeddedNavigator  嵌入导航器 (DataBindings)  数据绑定 (Advanced)  高级设置 Tag Text AccessibleDes ...

  6. HTML中DOM元素的子节点为空?!firstChild, lastChild, childeNodes[]为空

  7. CentOS 下安装 SNMP 服务

    CentOS 中搭建 SNMP 服务 0.前言 首先这个服务我不知道有什么用,学习CCNA的也许有了解.所以这里仅仅只是教做题,下面还有一些搜到的配置文件希望会大家有所帮助. 简单网络管理协议(SNM ...

  8. 提高 iOS App 通知功能启用率的三个策略

    我们都知道推送通知在 App 运营中的作用巨大.但是,很多用户却并不买帐,App 第一次启动提示是否「启用推送通知」时,他们直接选择了「否」. 是的,最近我本人就转变成了这样的人 - 认真地评估每个应 ...

  9. 缩点 CF893C Rumor

    CF893C Rumor 有n个人,其中有m对朋友,现在你有一个秘密你想告诉所有人,第i个人愿意出价a[i]买你的秘密,获得秘密的人会免费告诉它的所有朋友(他朋友的朋友也会免费知道),现在他们想出最少 ...

  10. To 高一

    Linux 坑待填 Special Judge 什么是 Special Judge?有的题目会让你输出任意一个解即可AC,或者是让你输出部分答案能取得本测试点部分得分,或者是按照方案的优秀程度给你分, ...