个人对于反射的学习总结以及经验,在认真学习反射之前,一直不能理解为什么要用反射,也不知道反射主要运用点在哪里,但是听说反射很重要。
反射是什么? 反射的使用是一种动态编程,主要是可以在运行中创建对象,调用方法、可以获取类中的一切。反射可以干什么? (1)代理模式 代理模式被用在Spring的AOP中 代理模式在日志实现中例如log4j (2)获取类中的全部信息(变量、方法这些,还要就是注解,自定义注解)。 (3)有一句话说的好,不存在完美的框架,虽然反射会破坏封装性,但是也可以让你修改原本封装好的私有变量,或者私有方法。 (4)跳过编译过程注:代码段都是用了junit进行单员测试写的,需要获得源码可以去我的github获取 在reflex分支 我的github地址
在面向对象的世界里,万事万物皆对象。(java语言中,静态的成员、普通数据类型除外) 类是不是对象呢?类是(哪个类的对象呢?)谁的对象呢? 类是对象,类是java.lang.Class类的实例对象
首先泛型的概念大家都知道、但是集合类中泛型在底层实现的时候存放的都是Object类型,基本所有的基本类型或者自己创建的对象都是Object的子类,所以我一个ArraysList 也可以存放String的变量,只要在编译阶段使用反射跳过泛型,不然直接调用add方法,编译会过不去,就会报错。
/** * 泛型只是为了防止编译过程中传入不符合自己定义泛型的对象(输入错误) * 还说明编译以后的泛型是去泛型化的,泛型只在编译阶段有效,反射会绕过编译 * 底层存储还是用Object类型存储的,下面就来证明这个。 * 这个例子就是往ArrayList<Interge>泛型中插入字符串 */ @Test public void test3() throws Exception { ArrayList<Integer> arr1 = new ArrayList<Integer>(); arr1.add(1); Class c = arr1.getClass(); Method m = c.getMethod("add", Object.class); m.invoke(arr1,"字符串"); for(Object i : arr1){ System.out.println(i); } }结果如下图: 可见ArraysList里面保存了字符串。
编译时刻加载类是静态加载类、运行时刻加载类是动态加载类
void关键字都存在类类型
就像底下这个代码一样: 比如我们完成了Peson类,但是noExist类不存在,如果采用new 创建一个对象的方式,就无法运行,如果使用反射,就可以运行。 1.在项目中如果要先对已经完成的代码,进行测试就可以采用动态加载的方式。 2.例如企业中更新软件,不是删除原来的代码,而是采用动态加载的方式
/** * 静态加载在编译的时候加载,例如本例下面,如果没有Student * 就会报错,但是我有Person类,我输入Person也不能过编译 * 动态加载就可以避免这种情况(也就是使用反射的方法) * 静态加载引发的问题 */ @Test public void test(){ String chose = "Student"; if(chose.equals("Person")){ Person p = new Person(); p.toString(); }else if(chose.equals("Student")){ Student t = new Student(); t.toString(); } // else{ // noExist no = new noExist(); // } } /** * 使用动态加载,来解决上面这个问题 * 虽然没有noExist类但是可以允许使用其他分支 * 而第一个在编译阶段都过不去 */ @Test public void test1() throws Exception { String chose ="Person"; if(chose.equals("Person")){ Person p = new Person(); System.out.println(p.toString()); }else if("noExist".equals(chose)){ Class c = Class.forName("com.imooc.reflex.noExist"); Object e = c.newInstance(); e.toString(); } }