0x01 前言
学习了本章,那么如何获取类的名称与类的方法,就都可以大概了解,也可以为后面学习之路,扫除一些困难。
0x01.1 目录结构
# 目录结构├── 反射│ └── java动态加载类3│ ├── Test.java (用来做测试的方法)│ ├── Word.java
0x01.2 例子-Word类(用于理解的)
// 该类具体路径: 反射.java获取类信息3.Wordpackage 反射.java获取类信息3;public class Word {public void start() {System.out.println("start() 公共方法被成功访问");}public void end() {System.out.println("end() 公共方法被成功访问");}public String save(int id, String title, String content) {return "id: " + id + "; " + "title: " + title + "; " + "content: " + content;}public String add(String title, String content) {return "title: " + title + "; " + "content: " + content;}private String upload(String[] files) {return "upload() 私有方法被成功访问";}private String delUpload() {return "delUpload() 私有方法被成功访问";}}
0x02 获取当前类名称的方法
0x02.1 getName()
getName() //得到类名称(包含路径)
// 例如现在获取 int, String, double, Double, void 的类名称(包含路径)// 可以这样操作package 反射.java获取类信息3;public class Test {public static void main(String[] args) {Class c1 = int.class;Class c2 = String.class;Class c3 = double.class;Class c4 = Double.class;Class c5 = void.class;System.out.println(" ");System.out.println("============int.class===============");System.out.println(c1.getName());System.out.println("====================================");System.out.println(" ");System.out.println("============String.class===============");System.out.println(c2.getName());System.out.println("====================================");System.out.println(" ");System.out.println("============double.class===============");System.out.println(c3.getName());System.out.println("====================================");System.out.println(" ");System.out.println("============Double.class===============");System.out.println(c4.getName());System.out.println("====================================");System.out.println(" ");System.out.println("============void.class===============");System.out.println(c5.getName());System.out.println("====================================");System.out.println(" ");}}// 运行结果============int.class===============int================================================String.class===============java.lang.String================================================double.class===============double================================================Double.class===============java.lang.Double================================================void.class===============void====================================
// 获取普通类的路径,也是一样的例如获取一下 0x01.2 例子-Word类 的类名称(包含路径)package 反射.java获取类信息3;public class Test {public static void main(String[] args) {Class w = Word.class;System.out.println(w.getName());}}// 运行结果反射.java获取类信息3.Word
0x02.2 getSimpleName()
getSimpleName() //得到类的简写名称(不包含包路径)
// 例如现在获取 int, String, double, Double, void 的类名称(不包含包路径)// 可以这样操作package 反射.java获取类信息3;public class Test {public static void main(String[] args) {Class c1 = int.class;Class c2 = String.class;Class c3 = double.class;Class c4 = Double.class;Class c5 = void.class;System.out.println(" ");System.out.println("============int.class===============");System.out.println(c1.getSimpleName());System.out.println("====================================");System.out.println(" ");System.out.println("============String.class===============");System.out.println(c2.getSimpleName());System.out.println("====================================");System.out.println(" ");System.out.println("============double.class===============");System.out.println(c3.getSimpleName());System.out.println("====================================");System.out.println(" ");System.out.println("============Double.class===============");System.out.println(c4.getSimpleName());System.out.println("====================================");System.out.println(" ");System.out.println("============void.class===============");System.out.println(c5.getSimpleName());System.out.println("====================================");System.out.println(" ");}}// 运行结果============int.class===============int================================================String.class===============String================================================double.class===============double================================================Double.class===============Double================================================void.class===============void====================================
// 获取普通类的路径,也是一样的例如获取一下 0x01.2 例子-Word类 的类名称(不包含包路径)package 反射.java获取类信息3;public class Test {public static void main(String[] args) {Class w = Word.class;System.out.println(w.getSimpleName());}}// 运行结果// 只返回类一个 Word.java 的类名称 WordWord
0x03 获取当前类所有的方法
0x03.1 getMethods()
getMethods() // 获取的是所有的public的方法,包括父类继承而来的
// 例如现在要获取 0x01.2 例子-Word类 所有public的方法,包括父类继承而来的package 反射.java获取类信息3;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {// 获取Runtime类对象Class w = Class.forName("反射.java获取类信息3.Word");// 通过类类型,创建该类对象Object wObject = w.newInstance();// 获取类对象的运行时类的Class对象Class wc = wObject.getClass();/*** Method类, 方法对象* 一个成员方法就是一个Method类对象* getMethods()方法 获取的是所有的public的函数方法, 包括父类继承而来的*/Method[] ms = wc.getMethods();for (int i = 0; i < ms.length; i++) {System.out.println(" ");System.out.println("====================================");System.out.println("方法名称是: " + ms[i].getName());// 获取参数类型-->得到的是参数列表的类型的类类型Class[] paramTypes = ms[i].getParameterTypes();for (int j = 0; j < paramTypes.length; j++) {System.out.println(" " +"参数" + (j+1) +"类型: " + paramTypes[j].getName() + ",");}System.out.println("方法的返回值的类类型: " + ms[i].getReturnType());}} catch (Exception e) {e.printStackTrace();}}}// 运行结果// 其中 add, start, save, end 是 Word类的公共方法// 其他的都是 Word类的默认父类方法====================================方法名称是: add参数1类型: java.lang.String,参数2类型: java.lang.String,方法的返回值的类类型: class java.lang.String====================================方法名称是: start方法的返回值的类类型: void====================================方法名称是: save参数1类型: int,参数2类型: java.lang.String,参数3类型: java.lang.String,方法的返回值的类类型: class java.lang.String====================================方法名称是: end方法的返回值的类类型: void====================================方法名称是: wait参数1类型: long,参数2类型: int,方法的返回值的类类型: void====================================方法名称是: wait参数1类型: long,方法的返回值的类类型: void====================================方法名称是: wait方法的返回值的类类型: void====================================方法名称是: equals参数1类型: java.lang.Object,方法的返回值的类类型: boolean====================================方法名称是: toString方法的返回值的类类型: class java.lang.String====================================方法名称是: hashCode方法的返回值的类类型: int====================================方法名称是: getClass方法的返回值的类类型: class java.lang.Class====================================方法名称是: notify方法的返回值的类类型: void====================================方法名称是: notifyAll方法的返回值的类类型: void
0x03.2 getDeclaredMethods()
getDeclaredMethods() // 获取的是所有该类自己声明的方法,不问访问权限
package 反射.java获取类信息3;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {// 获取Runtime类对象Class w = Class.forName("反射.java获取类信息3.Word");// 通过类类型,创建该类对象Object wObject = w.newInstance();// 获取类对象的运行时类的Class对象Class wc = wObject.getClass();/*** Method类, 方法对象* 一个成员方法就是一个Method类对象* getDeclaredMethods()方法 获取的是所有该类自己声明的方法* 不问访问权限,父类继承来的就没有类,必须是该类自己声明的,才能获取*/Method[] mds = wc.getDeclaredMethods();for (int i = 0; i < mds.length; i++) {System.out.println(" ");System.out.println("====================================");System.out.println("方法名称是: " + mds[i].getName());// 获取参数类型-->得到的是参数列表的类型的类类型Class[] paramTypes = mds[i].getParameterTypes();for (int j = 0; j < paramTypes.length; j++) {System.out.println(" " +"参数" + (j+1) +"类型: " + paramTypes[j].getName() + ",");}System.out.println("方法的返回值的类类型: " + mds[i].getReturnType());}} catch (Exception e) {e.printStackTrace();}}}// 运行结果// 获取的是 Word这个类所有的方法====================================方法名称是: add参数1类型: java.lang.String,参数2类型: java.lang.String,方法的返回值的类类型: class java.lang.String====================================方法名称是: start方法的返回值的类类型: void====================================方法名称是: save参数1类型: int,参数2类型: java.lang.String,参数3类型: java.lang.String,方法的返回值的类类型: class java.lang.String====================================方法名称是: upload参数1类型: [Ljava.lang.String;,方法的返回值的类类型: class java.lang.String====================================方法名称是: delUpload方法的返回值的类类型: class java.lang.String====================================方法名称是: end方法的返回值的类类型: void
0x04 调用某个类指定的成员方法
通过 getMethods() 与 getDeclaredMethods() 方法, 我们学习到了如何去获取类的名称和参数类型与返回类型。
那么如果我现在想要调用 某个类的指定方法 那就可以使用此方法。
0x04.1 getMethod()
getMethod() // 获取的是当前类某个public的方法,包括父类继承而来的
# 使用方法:# 方法1:Method method = clazz.getMethod("方法名");# 方法2:Method method = clazz.getMethod("方法名", 方法参数类型,多个参数用","号隔开);Method method = clazz.getMethod("方法名",String.class, int.class);
0x04.2 getDeclaredMethod()
getDeclaredMethod() // 获取的是该类自己声明的某个方法,不问访问权限
# 使用方法:# 方法1:Method method = clazz.getDeclaredMethod("方法名");# 方法2:Method method = clazz.getDeclaredMethod("方法名", 方法参数类型,多个参数用","号隔开);Method method = clazz.getDeclaredMethod("方法名",String.class, int.class);
0x04.3 invoke() - 通过反射调用方法
# 反射调用方法获取到java.lang.reflect.Method对象以后我们就可以通过Method对象的invoke方法来调用类方法# 调用类方法代码例子:method.invoke(方法实例对象, 方法参数值,多个参数用","号隔开);method.invoke(方法实例对象, "参数值1", "参数值2", "参数值3");
0x04.4 getMethod() 与 getDeclaredMethod() 使用例子
因为 getMethod() 与 getDeclaredMethod() 两个在实际调用中是一样的,
所以就不一个个区分啦
# 例子1-调用无参数的公共start()方法# 使用的getMethod()package 反射.java获取类信息3;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {Class w = Class.forName("反射.java获取类信息3.Word");// 通过类类型,创建该类对象Object wObject = w.newInstance();// 获取Word类 start方法Method a = w.getMethod("start");// 调用Word类 start方法Object aa = a.invoke(wObject);System.out.println(aa);} catch (Exception e) {e.printStackTrace();}}}# 运行结果start() 公共方法被成功访问null
# 例子2-调用有参数的公共save()方法# 使用的getMethod()package 反射.java获取类信息3;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {Class w = Class.forName("反射.java获取类信息3.Word");// 通过类类型,创建该类对象Object wObject = w.newInstance();// 获取Word类 save方法Method a = w.getMethod("save", int.class, String.class, String.class);// 调用Word类 save方法Object aa = a.invoke(wObject, 1, "标题1", "内容1");System.out.println(aa);} catch (Exception e) {e.printStackTrace();}}}// 运行结果id: 1; title: 标题1; content: 内容1
# 例子3-调用有数组参数的私有upload()方法# 使用的getDeclaredMethod()# 注意: 在调用私有方法的时候# 必须要在使用 getDeclaredMethod() 的时候设置 setAccessible(true);# 不然无法调用私有方法package 反射.java获取类信息3;import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try {Class w = Class.forName("反射.java获取类信息3.Word");// 通过类类型,创建该类对象Object wObject = w.newInstance();// 获取Word类 upload方法Method a = w.getDeclaredMethod("upload", String[].class);// 忽略访问修饰符的检查,这样就可以调用私有方法或是成员变量a.setAccessible(true);// 这里有个坑// 当我们的参数是数组的时候, 不能想当然的传个数组进去// 不然会提示:// java.lang.IllegalArgumentException: wrong number of arguments// 这是因为在java中 对方法传一个数组的时候, java会认为是多个参数// 解决方案: 把 fileArr 改为 new Object[]{fileArr} 传进去即可String[] fileArr = new String[]{"上传1", "上传2"};// 调用Word类 upload方法Object aa = a.invoke(wObject, new Object[]{fileArr});System.out.println(aa);} catch (Exception e) {e.printStackTrace();}}}// 运行结果upload() 私有方法被成功访问
