本文主要是介绍通过反射了解泛型的本质,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
通过Class,Method来认识泛型的本质
我们知道Java中集合的泛型是防止错误输入的,例如ArrayList<String>list1=new ArrayList<String>();
接下来如果再有list1.add(20);
系统便提示错误,程序无法通过编译,以为list1的类型已被指定为String,那么我们看以下代码
Class c1=list.getClass();
Class c2=list1.getClass();
System.out.println(c1==c2);
此时系统输出的是却是true,未使用泛型的list和使用泛型指定唯一类型String的list1具有相同的类类型(getClass()方法返回类的类类型)吗??
原因在于——泛型只在编译阶段有效,编译完成后自动去泛型化,而反射操作都是编译之后的操作,下面我们举例加深理解。
package 反射与泛型;
import java.lang.reflect.Method;
import java.util.*;
public class Example {public static void main(String[] args) {ArrayList list=new ArrayList();ArrayList<String>list1=new ArrayList<String>();list1.add("hello");//list1.add(20);错误的,编译不通过Class c1=list.getClass();Class c2=list1.getClass();System.out.println(c1==c2);//反射的操作都是编译之后的操作///** c1==c2结果返回true说明编译之后集合的泛型是去泛型化的* Java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了* 验证:我们可以通过方法的反射来操作,绕过编译* */try {Method m=c2.getMethod("add", Object.class);m.invoke(list1, 20);//绕过编译操作就绕过了泛型System.out.println(list1.size());} catch (Exception e) {e.printStackTrace();} }
}
很显然,我们成功地使用反射绕过了泛型为list1添加了一个int类型的元素20,说明绕过绕过编译操作也就绕过了泛型。
总结
此刻,我们对于泛型和反射有了一定的认识,但是编译过程到底是如何实现的,底层类的加载执行又有哪些细节,还有待于深入学习。
这篇关于通过反射了解泛型的本质的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!