有如下定义
ArrayList<String> b = new ArrayList<String>();
则执行b.add(20);肯定会出错
而利用反射机制则可以实现b.add(20);的功能,执行如下代码,将成功添加20到b中
Class cc = b.getClass();
Method mm = cc.getMethod("add", Object.class);
System.out.println("增加之前b的长度:"+b.size());
mm.invoke(b, 20);
System.out.println("增加之后b的长度:"+b.size());
运行结果截图,20确实添加到了b中:
注意:
输出的时候不能直接get,因为里面装的是Integer类型的值,而取出来默认是String类型的,则会出现强制类型转换错误:Integer类型不能转换为String类型
但可以用反射来解决:
虽然平时我们并不会这样用…谁没事找事写个String类型的集合来放Integer呢,所以这里只是举了个反射的小例子。但为什么使用反射机制就没错呢?
因为泛型<>只是为了在编译时期防止输入错误,上面规定了泛型为String类型,则就不能进行b.add(20)操作,因为编译会检测到20和String类型不匹配,而其实到了运行时期已经没有泛型了,相当于ArrayList b = new ArrayList();
所以,反射就是绕过编译直接到运行
利用反射机制获取String类类对象的三种方式:
1、Class c = String.class;
2、String str = "a"; Class c = str.getClass();
3、ClassForName("java.lang.String");
获取类对象后,通过类对象获取String类的方法:
Method m[] = c.getMethod() 获取所有public方法(包括父类继承的)
Method m[] = c.getDeclareMethod() 获取自身定义的所有方法
通过获取到的类方法来执行:
Method mm = m[0];
Class cc[] = mm.getParameterType() 得到方法参数类型
Method mm = c.getMethod(“methodName”, Class[]) 得到方法
String a = "aaa";
mm.invoke(a, param[]); 用a对象来执行mm方法,相当于a.methodName()
举个栗子:
Class c = ArrayList.class;
Method m =c.getMethod("toString"); //得到toString方法,该方法没有参数,因此可只写一个方法名
ArrayList<String> al = new ArrayList<String>();
al.add("a");
al.add("b");
al.add("c");
System.out.println(m.invoke(al)); //输出执行结果
结果截图如下:
如果需要的执行的方法带参数的话,就在后面加上 “类名”.class,例如:
String类的substring方法如下
执行如下代码,得到结果“345”: