集合框架中经常会使用泛型指定集合中所存放元素的类型,保证集合的统一性,从集合中取出元素的时候也避免了类型强制转换的操作,所以我们使用常规的方式来往集合中存放元素的时候,如果指定泛型,那么我们只能向集合内添加泛型类型的对象,如果不指定泛型,那么可以往集合中添加任何类型的对象,因为此时默认元素是Object类的对象,取出时也需要类型强制转换,就如下面代码:

 ArrayList list = new ArrayList();
list.add(1);
list.add("s"); //插入的都是Object的对象类型
System.out.println(list); ArrayList<String> list1 = new ArrayList<String>();
list1.add("s");
list1.add(2); //这是错误的

  这就可以看出泛型的区别,最后一行代码会被编译器报错,下面分别获取list和list1的类类型,并进行比较:

 Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1 == c2);

  因为list和list1属于两个不同的对象,由此我们推断c1和c2也是不相等的两个类类型,但实际上结果输出true,因为反射获取到类类型相当于字节码的执行阶段,那么c1和c2肯定属于执行阶段的比较,所以我们得到结论:编译之后集合的泛型是去泛型化的,所有的集合类的类类型都相等,泛型就不存在了,泛型只是在编译的时候约束元素的类型,只在编译阶段有效,所以我们可以利用反射的原理,绕过编译,让list1也可以存放不同类型的元素:

         try {
Method m = c2.getMethod("add", Object.class);
m.invoke(list1, 100); //利用反射,在运行阶段执行从而绕过编译的操作
System.out.println(list1.size());
System.out.println(list1);
//不能用foreach来遍历
//用iterator遍历
Iterator it = list1.iterator();
while(it.hasNext()) {
Object obj1 = it.next();
System.out.println(obj1);
}
//用for遍历
for(int i = 0;i < list1.size();i++) {
Object obj2 = list1.get(i);
System.out.println(obj2);
}
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

  上面代码通过getMothod方法获得方法对象,然后通过invoke方法来执行方法,这样就可以在带有泛型的集合中存放不同的元素,这样就利用反射绕过了编译的限制;因为无法确定指定方法是否存在,因此需要抛出异常;遍历的时候我们可以使用iterator迭代器或者for循环进行遍历,但是因为类型不一致的原因,所以不能用foreach进行遍历

通过Java反射来理解泛型的本质的更多相关文章

  1. Java反射的理解(六)-- 通过反射了解集合泛型的本质

    Java反射的理解(六)-- 通过反射了解集合泛型的本质 上述写了那么多,我们可能会有个疑问,为什么要用反射,步骤比我们常规的加载类操作复杂多了,别急,这个问题我最后才解答,我们先来了解集合泛型的本质 ...

  2. java反射--通过反射了解集合泛型的本质

    通过Class,Method来认识泛型的本质 package com.reflect; import java.lang.reflect.Method; import java.util.ArrayL ...

  3. [Java反射基础四]通过反射了解集合泛型的本质

    本文接上文"方法反射的基本操作",利用反射了解下java集合中泛型的本质 1.初始化两个集合,一个使用泛型,一个不使用 ArrayList list1 = new ArrayLis ...

  4. Java基础 -- 深入理解泛型

    一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 而泛型很好的解决了这个问题,这也是Java SE5的重大 ...

  5. Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题

    在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...

  6. (转)JAVA反射机制理解

    JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没 ...

  7. java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)

    原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...

  8. Java 反射的理解

    反射反射,程序员的快乐,今天你快乐了吗?如果你不快乐,没关系,接下来让你快乐起来! 一.什么是反射? 通过百度百科我们可以知道,Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  9. java通过反射了解集合泛型的本质

随机推荐

  1. 旅行(Dijkstra)问题

    问题:输入: 输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个:   接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车 ...

  2. Spring JdbcTemplate 的使用与学习(转)

    紧接上一篇 (JdbcTemplate是线程安全的,因此可以配置一个简单的JdbcTemplate实例,将这个共享的实例注入到多个DAO类中.辅助的文档) Spring DAO支持 http://ww ...

  3. vim下使用ctags+taglist

    好几年前用过,但是后来就生疏了,好其次都没法鼓起勇气再捡起来...今天不得不用,那既然捡起来了,就好好的记录一下. 简介及安装 ctags是一个应用程序,可以用它来生产当前目录下所有c文件中变量和函数 ...

  4. Python代码性能优化技巧

    摘要:代码优化能够让程序运行更快,可以提高程序的执行效率等,对于一名软件开发人员来说,如何优化代码,从哪里入手进行优化?这些都是他们十分关心的问题.本文着重讲了如何优化Python代码,看完一定会让你 ...

  5. Ioc注解

    注解: 添加注解时,需要添加context的相关 <?xml version="1.0" encoding="UTF-8"?> <beans ...

  6. mybatis 使用resultMap实现关联数据的查询(association 和collection )

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...

  7. 看过《大湿教我写.net通用权限框架(1)之菜单导航篇》之后发生的事(续)——主界面

    引言 在UML系列学习中的小插曲:看过<大湿教我写.net通用权限框架(1)之菜单导航篇>之后发生的事 在上篇中只拿登录界面练练手,不把主界面抠出来,实在难受,严重的强迫症啊.之前一直在总 ...

  8. Objective-C 之优雅的命名(转)

    There are only two hard things in Computer Science: cache invalidation and naming things. 在计算机科学中只有两 ...

  9. LINUX下 my.cnf php.ini的位置

    my.cnf:/etc/ php.in:/usr/local/php/etc/

  10. wordpress编辑主题时报错Warning: scandir() has been disabled for security reasons in

    在ubuntu下面安装了一个wordpress程序,在后台什么都没干,编辑主题时,发现页面中报下面的错误. notice: /home/wwwroot/test.localhost/wordpress ...