通过Java反射来理解泛型的本质
集合框架中经常会使用泛型指定集合中所存放元素的类型,保证集合的统一性,从集合中取出元素的时候也避免了类型强制转换的操作,所以我们使用常规的方式来往集合中存放元素的时候,如果指定泛型,那么我们只能向集合内添加泛型类型的对象,如果不指定泛型,那么可以往集合中添加任何类型的对象,因为此时默认元素是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反射来理解泛型的本质的更多相关文章
- Java反射的理解(六)-- 通过反射了解集合泛型的本质
Java反射的理解(六)-- 通过反射了解集合泛型的本质 上述写了那么多,我们可能会有个疑问,为什么要用反射,步骤比我们常规的加载类操作复杂多了,别急,这个问题我最后才解答,我们先来了解集合泛型的本质 ...
- java反射--通过反射了解集合泛型的本质
通过Class,Method来认识泛型的本质 package com.reflect; import java.lang.reflect.Method; import java.util.ArrayL ...
- [Java反射基础四]通过反射了解集合泛型的本质
本文接上文"方法反射的基本操作",利用反射了解下java集合中泛型的本质 1.初始化两个集合,一个使用泛型,一个不使用 ArrayList list1 = new ArrayLis ...
- Java基础 -- 深入理解泛型
一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 而泛型很好的解决了这个问题,这也是Java SE5的重大 ...
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...
- (转)JAVA反射机制理解
JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没 ...
- java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)
原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...
- Java 反射的理解
反射反射,程序员的快乐,今天你快乐了吗?如果你不快乐,没关系,接下来让你快乐起来! 一.什么是反射? 通过百度百科我们可以知道,Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...
- java通过反射了解集合泛型的本质
随机推荐
- CSS布局自适应高度解决方法
这是一个比较典型的三行二列布局,每列高度(事先并不能确定哪列的高度)的相同,是每个设计师追求的目标,按一般的做法,大多采用背景图填充.加JS脚本的方法使列的高度相同,本文要介绍的是采用容器溢出部分隐藏 ...
- C语言+SDL2 图形化编程
程设大作业小火车第一版本是命令行界面,第二版本是图形化界面,由于egg库对以后工程开发没有用,我不想用egg库,花了很长时间浏览了一下OpenGL的中文教程,觉得好复杂,需要看很多很多才能写出个简单的 ...
- 写在SDOI2016Round1前的To Do List
理性的整理了一下自己的不足. 计算几何啥都不会,字符串类DP毫无练习,数据结构写的不熟,数论推不出式子,网络流建模常建残: 需要达成的任务: 一.网络流: 熟练网络流的板子(之前一直仰慕zkw费用流, ...
- [NOIP2010] 提高组 洛谷P1540 机器翻译
题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...
- IOS开发 证书总结
开发者证书 ------>> 首先你必须获得apple开发者证书,上图这个文件就是apple开发者证书,只要有apple的开发者账号就可以下载到,此证书可以直接到 developer ...
- TCP Socket Establish;UDP Send Package Process In Kernel Sourcecode Learning
目录 . 引言 . TCP握手流程 . TCP connect() API原理 . TCP listen() API原理 . UDP交互过程 . UDP send() API原理 . UDP bind ...
- JAVA输入一个整数,求出其所有质因数
首先得求出能整除A的数,再判断I是否是质数!!! import java.util.*; public class aa { public static void main(String[] args ...
- MyEclipse------随机流(能读也能写数据)
RandomAccessFile流指向文件时,不刷新文件. 其中seek(long a)用来定位RandomAccessFile流的读写位置,其中参数a确定读写位置距离文件开头的字节个数. other ...
- tp框架表单验证
之前的表单验证都是用js写的,这里也可以使用tp框架的验证.但是两者比较而言还是js验证比较好,因为tp框架验证会运行后台代码,这样运行速度和效率就会下降. 自动验证是ThinkPHP模型层提供的一种 ...
- Python socket编程之一:
soket 编程步骤 # -*- coding: utf-8 -*- ################################################################# ...