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. Djangorestframework编写post接口

    前提:已经有Django环境 一.安装 pip install djangorestframework 二.编写视图 import json from django.shortcuts import ...

  2. [java]基于UDP的Socket通信Demo

    java课编程作业:在老师给的demo的基础上实现客户端发送数据到服务器端,服务器端接受客户端后进行数据广播. 整体功能类似于聊天室,代码部分不是太难,但是在本机测试的时候出现这样的问题: 服务端通过 ...

  3. c++调用c#写的DLL

    c++调用c#写的DLL: 此文章演示了建立c#的dll: c++建立工程,引入dll: 不能解决的问题: 指定dll的路径,在代码里面直接写 #using "xxx.dll" 必 ...

  4. ASP.NET Core URL Rewrite中间件

    URL重写是基于一个或多个预置规则修改请求URL的行为.URL重写在资源位置和访问地址之间创建了一种抽象,这样二者之间就减少了紧密的联系.URL重写有多种适用的场景: 临时或永久移动或替换服务器资源, ...

  5. MySQL数据库(四)

    操作数据库表的内容: -- 向表中插入数据:insert into table_name values(now(),'a'); insert into student (id,name,sex) va ...

  6. Sublime Text3 最新版3207 安装及破解

    注:原文地址 https://www.abbeyok.com/archives/337 Sublime Text 3最近更新了新版本,最新版本:3207,之前的license无效了,新版破解方法如下: ...

  7. [Maven实战-许晓斌]-[第二章]-2.4设置HTTP代理

  8. Python一篇学会多进程

    阅读目录 1. Process 2. Lock 3. Semaphore 4. Event 5. Queue 6. Pipe 7. Pool 序. multiprocessing python 中的多 ...

  9. 用JS实现汉字转拼音

    <!DOCTYPE HTML> <html> <head> <title>用JS实现汉字转拼音</title> <meta chars ...

  10. python difflib详解

    difflib -帮助进行差异化比较 这个模块提供的类和方法用来进行差异化比较,它能够生成文本或者html格式的差异化比较结果,如果需要比较目录的不同,可以使用filecmp模块. class dif ...