我是靠谱客的博主 斯文水壶,这篇文章主要介绍java高级开发学习之--反射机制(3),现在分享给大家,希望可以做个参考。

1.通过前面的学习,自己感觉其实反射机制也没有很神秘,无非就是类本身就是一个对象,通过类的类类型去动态加载类。
2.今天学习类的方法的反射操作以及通过反射来了解集合泛型的本质。

A.方法的反射操作:
首先我们创建一个类

复制代码
1
2
3
4
5
6
7
8
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()); } }

接着创建测试类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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方法。

复制代码
1
public Method getMethod(String name, Class<?>... parameterTypes)

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

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

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

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

复制代码
1
2
3
//获取方法print(String,String) Method mt=c.getMethod("print",String.class,String.class); o = mt.invoke(a1, "abcA","Acv");

B.通过反射了解集合泛型的本质:
完整代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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高级开发学习之--反射机制(3)的全部内容,更多相关java高级开发学习之--反射机制(3)内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部