今天给大家po出我的第三份关于学习反射的笔记,关于对类的方法的反射。其中包括静态方法,普通方法,带参数的方法,以及最重要的String[]数组的方法的反射以及需要注意的细节问题,都是基础,所以请各位多多包涵!
有关前面两篇文章请看下面:
//===================================================
// 反射类的方法
//===================================================
本文由机智猫亲手写,转载请尊重版权:http://blog.csdn.net/nthack5730/article/details/49888833
| 首先,通过Class获取类的字节码
|Class clazz = Class.forName("com.marer.reflect.Person");
|
| 1.反射无参的方法: public void aa1()
|Method method = clazz.getMethod("aa", null);
|第一个参数:方法名;第二个参数:方法的参数,若为无参方法可以为null值
|
|执行方法:
|method.invoke(p, null);//第一个参数:你要调用哪个对象的方法,假设new了一个新的对象p;第二个参数:被反射的对象的方法所需要的参数,如果无参数则传null
|
|
|
| 2.反射带一个或者多个参数的方法: public void aa(String name, int age)
|Method method = clazz.getMethod("aa", String.class, int.class);//第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用
|第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用
|
|执行方法:
|method.invoke(p, "老张,成功了", 23);//第一个参数:你要调用哪个对象的方法,假设new了一个新的对象p;第二个参数:可变参数
|
|
|
| 3.反射带数组的方法,并返回Class数组: public Class[] aa(String name, int[] ages)
|Method method = clazz.getMethod("aa", String.class, int[].class);//在这里,原方法第二个参数中是个int数组,那么就传int[].class
|
|执行方法:
|Class cs[] = (Class[]) method.invoke(p, "老李,成功了", new int[]{1,2,3});
|
|
|
| 4.反射类的私有方法: private void aa(InputStream in)
|Method method = clazz.getDeclaredMethod("aa", InputStream.class);//private方法用getDeclaredMethod()
|method.setAccessible(true);//打开访问权限,暴力反射
|
|执行方法:
|Class cs[] = (Class[]) method.invoke(p, new FileInputStream("D:\\我的文档\\Q.txt"));
|
|
|
| 5.反射类的静态方法: public static void aa(int num)
|Method method = clazz.getMethod("aa", int.class);
|
|执行方法:
|method.invoke(123);//静态方法调用不需要对象,直接执行
|与普通方法不同,在静态方法中,因为静态方法是一直存在的,因此不需要通过对象的访问进行调用,只需要直接调用
|而需要通过对象调用的普通方法,执行的是对象内部的方法,对其他的对象没有影响
|
|
|
| 6.反射类的main方法,以及有且只有一个参数并且参数类型为数组的方法的反射、特殊的参数String[] 的反射方法:
|public static void main(String[] args)
|public static boolean doDelete(int[] ids)
|
|反射:
|Method method = clazz.getMethod("main", String[].class);//这里指定方法名为main,指定参数为String[]数组
|
|执行方法一:
|method.invoke(null, new Object[]{new String[]{"123","weq"}});//第一种方法,将String[]数组参数包装在数组中,到了invoke()里面就会对应拆分出一个String数组
|
|执行方法二:
|method.invoke(null, (Object) new String[]{"123","weq"});//第二种方法,推荐使用,将参数的数组包装在一个Object中,并且由JDK拆分,拆分出第一个参数就是数组,那么就会通过调用
|//注意:这里将String[]数组参数封装为(Object)对象是允许的因为Object对象是所有对象的始祖
|
|
|注意:1.上面的main方法的反射以及调用,适用所有的有且只有一个String[]数组为参数的方法,对于其他类型的数组可以不用包装,例如只有一个int[]参数的方法
|method.invoke(null, new int[]{1,2});//如果只有一个int[]数组为参数的反射,可以不用像上面那样封装,即使封了也没问题invoke(null, (Object)new int[]{1,2})
|
|
|注意:2.对于String和包装类(例如:Integer,Charater..),如果一个或多个参数都是同样的(String或包装类),就可以通过new 数组的形式进行invoke反射调用,例如:
|1.一个或多个String参数,必须都是String,如果有一个参数不一样(例如String和String[]数组都是不一样的,那么就不能够通过下面的方法进行反射调用方法
|类方法:public static void test(String s1, String s2)
|反射方法:Method method = clazz.getMethod("test", String.class, String.class);
|反射方法的invoke调用:method.invoke(null, new String[]{"asd","123"});
|//当然,上面的也可以通过普通的两个个字符串参数进行invoke调用
|
|
|
|2.一个或多个包装类的方法都是一样的:(Integer,Character...)
|类方法:public static void test6(Integer a1, Integer a2)
|反射方法:Method method = clazz.getMethod("test6", Integer.class,Integer.class);
|反射方法的invoke调用:method.invoke(null, new Integer[]{1,2});
|//必须注意:两个基础数据类型的int不能通过数组进行invoke反射调用,乖乖地一个个传参吧
|//Method method = clazz.getMethod("test4", int.class,int.class);
|//method.invoke(null, 1,2);
|
|3.但是对于两个或以上的String[]数组声明的方法就不可以用一个数组进行invoke调用
|类方法:public static void test8(String[] s1, String[] s2)
|反射方法:Method method = clazz.getMethod("test8", String[].class, String[].class);
|反射方法的invoke调用:method.invoke(null, new String[]{"abc","def"});//这时候是抛出参数要求长度不一的异常的
|//运行结果是抛异常的,因此证明是不能通过这种方法去进行invoke调用
|
|
|4.普通类也不能通过数组的方式进行invoke调用
|类方法:public static void test7(Person p1, Person p2)
|反射方法:Method method = clazz.getMethod("test7", Person.class,Person.class);
|反射方法的invoke调用:method.invoke(null, new Person(),new Person());//两个非String或非包装类就不能用数组来invoke反射调用
|
|本文由机智猫亲手写,转载请尊重版权:http://blog.csdn.net/nthack5730/article/details/49888833
|
|总结:通过上述几个样例,大家应该可以看到反射方法的invoke调用的不同的形式
| 其实只要注意有且只有一个String[]数组作为参数的方法的反射以及调用注意的问题就可以了【直接将String[]数组的参数强转成Object即可】
|除了多个String参数或多个包装类型的方法(都必须都是String类型的参数或包装类型)可以通过在invoke的时候传一个String[]数组参数以外
|其他方法都是必须按照参数的要求对号入座
|PS.一般情况为了避免造成不必要的麻烦,都建议按照参数的个数要求进行对号入座
|
本文由机智猫亲手写,转载请尊重版权:http://blog.csdn.net/nthack5730/article/details/49888833
关于之前写的Person类:
package com.marer.reflect; import java.io.InputStream; import java.util.List; public class Person { public String str = "aa"; int a = 1233; private int num = 4564564; private static int num2 = 9527; private int nums; private String name; public Person(){ System.out.println("person"); } public Person(String name){ System.out.println("person name:" + name); } public Person(String name, int age){ System.out.println("person name:" + name + "\tage:" + age); } private Person(List list){ System.out.println("list"); } //方法 public void aa(){ System.out.println("aa"); } public void aa(String name, int age){ System.out.println("person name:" + name + "\tage:" + age); } public Class[] aa(String name, int[] ages){ System.out.println("有返回值的"); return new Class[]{String.class}; } private void aa(InputStream in){ System.out.println(in); } public static void aa(int num){ System.out.println(num); } public static void main(String[] args){ System.out.println("main方法运行"); } public static void test(String[] args){ System.out.println("字符串数组参数方法调用成功"); } public static void test(String s1, String s2){ System.out.println("两个字符串"); System.out.println(s1); System.out.println(s2); } public static void test_1(String s1, String s2,String s3){ System.out.println("三个字符串"); System.out.println(s1); System.out.println(s2); System.out.println(s3); } public static void test2(int[] a1, int[] a2){ System.out.println("两个参数为数组的方法"); System.out.println(a1.length); for(int a: a1){ System.out.print(a+","); } System.out.println("\n"+a2.length); for(int a: a2){ System.out.print(a+","); } } public static void test3(int[] a1, int a2){ System.out.println("第一个参数为数组,第二个参数为普通类型的方法"); System.out.println(a1.length); for(int a: a1){ System.out.print(a+","); } System.out.println(a2); } public static void test4(int a1, int a2){ System.out.println("两个参数为普通类型int,用数组进行invoke"); System.out.println(a1); System.out.println(a2); } public static void test5(int[] a1){ System.out.println("int 数组"); for(int a:a1){ System.out.println(a); } } public static void test6(Integer a1, Integer a2){ System.out.println("两个参数为普通类型Integer,用数组进行invoke"); System.out.println(a1); System.out.println(a2); } public static void test7(Person p1, Person p2){ System.out.println("两个参数为普通类型Integer,用数组进行invoke"); System.out.println(p1); System.out.println(p2); } public static void test8(String[] s1, String[] s2){ System.out.println("两个字符串数组"); System.out.println(s1.toString()); System.out.println(s2.toString()); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public static int getNum2() { return num2; } public static void setNum2(int num2) { Person.num2 = num2; } public int getNums() { return nums; } public void setNums(int nums) { this.nums = nums; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
本文由机智猫亲手写,转载请尊重版权:http://blog.csdn.net/nthack5730/article/details/49888833
这次本文的Demo类:
package com.marer.reflect; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; import org.junit.Test; //反射类的方法 public class Demo3 { //反射类的方法:public void aa1() @Test public void test1() throws Exception{ Person p = new Person(); Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("aa", null);//第一个参数:方法名;第二个参数:方法参数 method.invoke(p, null);//第一个参数:你要调用哪个对象的方法;第二个参数:被反射的对象的方法所需要的参数 } //反射类的方法:public void aa(String name, int age) @Test public void test2() throws Exception{ Person p = new Person(); Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("aa", String.class, int.class);//第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用 method.invoke(p, "老张,成功了", 23);//第一个参数:你要调用哪个对象的方法;第二个参数:可变参数 } //反射类的方法:public Class[] aa(String name, int[] ages) @Test public void test3() throws Exception{ Person p = new Person(); Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("aa", String.class, int[].class);//在这里,原方法第二个参数中是个int数组,那么就传int[].class Class cs[] = (Class[]) method.invoke(p, "老李,成功了", new int[]{1,2,3}); System.out.println(cs[0]); } //反射类的私有方法:private void aa(InputStream in) @Test public void test4() throws Exception{ Person p = new Person(); Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getDeclaredMethod("aa", InputStream.class);//private方法用getDeclaredMethod() method.setAccessible(true);//打开访问权限,暴力反射 Class cs[] = (Class[]) method.invoke(p, new FileInputStream("D:\\我的文档\\Q.txt")); } //反射类的静态方法:public static void aa(int num) @Test public void test5() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("aa", int.class); method.invoke(123);//静态方法调用不需要对象 } //反射类的方法:public static void main(String[] args) @Test public void test6() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("main", String[].class);//这里指定方法名为main,指定参数为String[]数组 // method.invoke(null, new Object[]{new String[]{"123","weq"}});//第一种方法,将String[]数组参数包装在数组中,到了invoke()里面就会对应拆分出一个String数组 method.invoke(null, (Object) new String[]{"123","weq"});//第二种方法,推荐使用,将参数的数组包装在一个Object中,并且由JDK拆分,拆分出第一个参数就是数组,那么就会通过调用 //main方法的反射获取和调用 } //反射类方法:public static void test(String[] args) @Test public void test7() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test", String[].class); method.invoke(null, (Object) new String[]{"asd","123"}); } //反射类方法:public static void test(String s1, String s2) @Test public void test8() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test", String.class, String.class); method.invoke(null, new String[]{"asd","123"}); } //反射类方法:public static void test_1(String s1, String s2, String s3) @Test public void test8_1() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test_1", String.class, String.class,String.class); method.invoke(null, new String[]{"asd","123","456"}); } //反射类方法:public static void test2(int[] a1, int[] a2) @Test public void test9() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test2", int[].class,int[].class); method.invoke(null, new int[]{1,2,3},new int[]{4,5,6}); } //反射类方法:public static void test3(int[] a1, int a2) @Test public void test10() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test3", int[].class,int.class); method.invoke(null, new int[]{1,2,3},4); } //反射类方法:public static void test4(int a1, int a2) @Test public void test11() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test4", int.class,int.class); method.invoke(null, 1,2);//两个基础数据类型的int不能通过数组进行invoke反射调用,乖乖地一个个传参吧 } //反射类方法:public static void test5(int[] a1) @Test public void test12() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test5", int[].class); method.invoke(null, new int[]{1,2}); } //反射类方法:public static void test6(Integer a1, Integer a2) @Test public void test13() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test6", Integer.class,Integer.class); method.invoke(null, new Integer[]{1,2});//两个基础数据类型的int不能通过数组进行invoke反射调用 } //反射类方法:public static void test7(Person p1, Person p2) @Test public void test14() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test7", Person.class,Person.class); method.invoke(null, new Person(),new Person());//两个非String或非包装类就不能用数组来invoke反射调用 } //反射类方法:public static void test8(String[] s1, String[] s2) @Test public void test15() throws Exception{ Class clazz = Class.forName("com.marer.reflect.Person"); Method method = clazz.getMethod("test8", String[].class, String[].class); method.invoke(null, new String[]{"abc","def"});//运行结果是抛异常的 } }