您的位置:首页 > 编程语言 > Java开发

java高级开发学习之--反射机制(3)

2016-08-11 21:13 411 查看
1.通过前面的学习,自己感觉其实反射机制也没有很神秘,无非就是类本身就是一个对象,通过类的类类型去动态加载类。

2.今天学习类的方法的反射操作以及通过反射来了解集合泛型的本质。

A.方法的反射操作:

首先我们创建一个类

class A{
public void print(int a,int b){
System.out.println(a+b);
}
public void print(String a, String b){
System.out.println(a.toUpperCase()+","+b.toLowerCase());
}
}


接着创建测试类

public class ClassDemo2 {
public static void main(String[] args) {
A a1 = new A();
Class c = a1.getClass();

try {
//          Method m = c.getMethod("print", new Class[]{int.class,int.class});
Method m = c.getMethod("print", int.class,int.class);

//方法的反射操作
//a1.print(10, 20); 方法的反射操作是用m对象来进行方法调用   和a1.print调用的效果完全相同

//方法如果没有返回值返回null,有返回值返回具体的返回值
Object o = m.invoke(a1,new Object[]{10,20});

System.out.println("******************");

//获取方法print(String,String)
Method mt = c.getMethod("print", String.class,String.class);
o = mt.invoke(a1, "abcA","Acv");

} catch (Exception e) {
e.printStackTrace();
}
}
}


在测试类中有详细的注释:那么是什么意思呢,简单理解

本来调用类A中的print()方法时,我们得通过new A()创建A类的对象才能调用print()方法,也就是
A a = new A();

a.print(10,20);


而学习了反射后,我们发现调用print()方法还有别的方式

1.我们首先通过
Class c = a.getClass();
获取a对象的类类型。

2.通过
Method m = c.getMethod("print",int.class,int.class);
获取print方法。

public Method getMethod(String name, Class<?>... parameterTypes)


第一个参数代表 你所要获取的方法名;第二个是多参类型,表示你所要获取的方法的参数列表的参数类类型。

接着通过invoke方法来执行方法的反射操作

//方法如果没有返回值返回null,有返回值返回具体的返回值
//第一个参数是所要执行方法操作的对象,后面则是方法参数列表所要传的实际参数
Object o = m.invoke(a1,new Object[]{10,20});


至此,方法的反射操作即完成了。当然如果想调用A类的print(String a, String b)方法也是一样的操作了

//获取方法print(String,String)
Method mt=c.getMethod("print",String.class,String.class);
o = mt.invoke(a1, "abcA","Acv");


B.通过反射了解集合泛型的本质:

完整代码如下:

public class ClassDemo3 {
public static void main(String[] args) {
ArrayList list = new ArrayList();

ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");
//list1.add(20); 错误的,因为规定了类型为String
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1 == c2);
//反射的操作都是编译之后的操作

/**
* c1==c2结果返回true 说明编译之后集合的泛型是去泛型化的
* java中集合的泛型,是防止错误输入的,只在编译阶段有效
* 绕过编译就无效了
* 验证:我们可以通过方法的反射操作来绕过编译
*/
try {
Method m = c1.getMethod("add", Object.class);
m.invoke(list1, 100);
System.out.println(list1.size());
System.out.println(list1);
} catch (Exception e) {
e.printStackTrace();
}
}
}


很简短的几行代码,但是让我更深的理解了泛型的本质.

为什么
//list1.add(20);
这个是错误的呢,首先list1定义了泛型,String类型,那么在编译时,相当于给你规定了类型,必须add String类型的参数才行,所以当然是不能add 20的,但是 c1是等于c2的,为什么呢,因为泛型在编译之后就被去掉了,也就是说
ArrayList<String> list1 = new ArrayList<String>();
这行代码在编译后就变成了
ArrayList list1 = new ArrayList();
所以c1最后是等于c2的。

而当我们用反射来操作add方法时,却可以添加20,这是因为反射的操作是在编译之后执行的,因此,编译之后不存在泛型,所以可以添加20.

至此,我们可以指定泛型其实就是为了防止错误输入的,它并不神秘,它只在编译阶段有效,绕过编译就无效了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java