今天给大家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"});//运行结果是抛异常的
}
}