使用反射为泛型集合添加其他类型的数据时遇到的问题

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合进会去掉“类型”信息,使程序运行效率不受影响。

由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合虽加入其它类型的数据。

所以我们可以用反射为泛型集合添加其他类型的数据。

例1:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
  arrayList .add(10);
  arrayList .add(20);
  arrayList .getClass().getMethod("add",Object.class).invoke(arrayList ,"hbase");
  System.out.println(arrayList .get(2));//虽然索引为2的位置存的是String类型,但编译时编译器会认为arrayList .get(2)返回的时是Integer类型,但在运行取值时取的仍是                                         //String类型
输出:hbase

例2:

ArrayList<String> arrayList = new ArrayList<String>();
  arrayList1.add("hadopp");
  arrayList1.add("hive");
  arrayList1.getClass().getMethod("add",Object.class).invoke(arrayList1,25);
  System.out.println(arrayList1.get(2));//虽然索引为2的位置存的是Integer类型,但编译时编译器会认为arrayList .get(2)返回的时是String类型,但在运行取值时取的仍                                       //Integer类型

报错!!
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 at com.mobin.generic.GenericTest.main(GenericTest.java:20)

报错代码:System.out.println(arrayList1.get(2));

Integer不能转成String,但例1为会又不报ClassCastException异常呢?(大家也可以先想想原因是什么再看下面的分析)

下面分析下原因:

出现ClassCastException这个异常可以断定的是类型的转换错误。

原因就在Syststem.out.println这条语句,

上图是println()的所有重载方法,除了bool,char,char[],double,float,int,String,long类型外,当传入的参数是其他类型时被会被当作是Object从而调用println(Object)方法。

在例1中由于arrayList1.get(2)返回的是Integer所以调用的是println(Object)方法,验证:把鼠标放到println方法上即可.

好,我们再进入println(Object x)的源码去看看

参数都被自动的转成了String类型!!!

相当于Object x = arrayList.get(2);   //所有对象都属于Object

String s = String.valueOf(x);

所以不会报错。

再看第二段代码的println调用的是println(String x);

同样进入源码去看看:

相当于String x = arrayList.get(2);      //这里运行时arrayList.get(2)所得的值的类型是Integer,又相当于String x = Integer;所以才报错

时间: 2025-01-03 01:35:37

使用反射为泛型集合添加其他类型的数据时遇到的问题的相关文章

泛型学习第三天——C#读取数据库返回泛型集合 把DataSet类型转换为List&lt;T&gt;泛型集合

定义一个类: public class UserInfo    {        public System.Guid ID { get; set; } public string LoginName { get; set; } public string LoginPwd { get; set; }    } /// <summary> /// 获取UserInfo泛型集合 /// </summary> /// <param name="connStr"

读取数据库返回泛型集合 把DataSet类型转换为List&lt;T&gt;泛型集合

转自 http://www.cnblogs.com/wuhuisheng/archive/2012/04/26/2471733.html 1 /// <summary> 2 /// 获取UserInfo泛型集合 3 /// </summary> 4 /// <param name="connStr">数据库连接字符串</param> 5 /// <param name="sqlStr">要查询的T-SQL&

mui H5 js动态添加不同类型的数据

html页面需要添加的页面的数据格式 <ul class="mui-table-view" id="OA_task_1"> <li class="mui-table-view-cell"> <div class="mui-slider-right mui-disabled"> <a class="mui-btn mui-btn-bule">企业联系人</

C#5.0泛型集合类型简述

.NET中的泛型集合 在这里主要介绍常见的泛型集合,很多时候其并发时的线程安全性常常令我们担忧.因而简述下.NET并发时线程安全特性,其详情请见MSDN. 普通集合都不支持多重并发写操作 部分支持单线程写和并发读操作 同时.NET4添加了大量并发集合 首先介绍常见的泛型集合接口,其大部分都位于System.Collection.Generic命名空间. IEnumerable<T>,其可以获取一个IEnumerator<T>迭代器,如果从数据库的角度来看,前者是表,后者是游标,同时

java 27 - 7 反射之 通过反射越过泛型检查

之前学过的集合里面都有泛型,规定了泛型的类型以后,就不能往这个集合添加除了这个类型之外的类型数据了. 那么,有什么方法可以越过这个泛型,添加特定类型以外的类型数据么? 例子:  往ArrayList<Integer>集合中添加一个字符串String类型的数据 分析: 通过查看ArrayList的add()方法,可以知道,add(E e).E这个泛型是Object的. 就可以通过反射来直接调用ArrayList集合的add方法进行添加 1 public static void main(Stri

C#—类库、委托、is和as运算符、泛型集合

类库 类库(Class Library)是一个综合性的面向对象的可重用类型集合,这些类型包括:接口.抽象类和具体类.类库可以解决一系列常见编程任务(包括诸如字符串管理.数据收集.数据库连接以及文件访问等任务),还可以解决多种专用开发任务(控制台应用程序.桌面应用程序.WEB应用程序等). 优点:保密性好,用户无法看到方法结构体 缺点:如果这个方法不好用,使用者无法自己去更改它. 鼠标放在类上按下F12可以查看程序集 1.创建类库 类库创建完成,它默认public,并且没有主函数,无法进行启动,它

快速入门系列--CLR--03泛型集合

.NET中的泛型集合 在这里主要介绍常见的泛型集合,很多时候其并发时的线程安全性常常令我们担忧.因而简述下.NET并发时线程安全特性,其详情请见MSDN. 普通集合都不支持多重并发写操作 部分支持单线程写和并发读操作 同时.NET4添加了大量并发集合 首先介绍常见的泛型集合接口,其大部分都位于System.Collection.Generic命名空间. IEnumerable<T>,其可以获取一个IEnumerator<T>迭代器,如果从数据库的角度来看,前者是表,后者是游标,同时

使用泛型集合代替datatable作为返回值实现面向对象

开会的时候,师父说,我们在机房重构时,尽量不要用datatable作为返回值,改用泛型集合的方式,这样可以实现真正的面向对象.通过查资料和同学交流,把这个问题给解决了.对于泛型集合,我也有了一些认识. 一.对泛型集合的认识 1.存在于System.Collection,Generic的命名空间中,在用的时候,需要引用 2.泛型是具有占位符(类型参数)的类,结构,接口和方法.就是说,在泛型集合中加入的数据必须符合指定的类型<T>,否则编译时就会报错. 以上为设计模式培训实习生的内容. 那泛型集合

我在北京写代码 写出心中悲与喜 写出人间的悲欢离合 欢迎阅读 我的第三章 使用集合组织相关数据(泛型集合)

ArrayList arry = new ArrayList();            arry.Add("小明");            arry.Add("小D");            arry.Add("小B");            arry.Insert(2,"小狗");            arry.Remove("小狗");            arry.RemoveAt(0);