以前在了解Spring的类加载机制的时候,了解了java的反射机制。可是,我对反射理解一直不深。也一直有点疑惑:Spring为何利用反射建立对象?直接new对象和依靠反射建立对象有什么区别?什么是动态加载类?java
要想知道反射究竟是什么,首先须要知道java的类加载和对象建立的机制。.net
当咱们写完一个java文件的时候,后缀是.java。在咱们利用IDE执行java文件的时候,其实IDE也帮咱们运行了javac,即java编译器。编译器会将.java文件编译成.class文件。java虚拟机会去读取.class文件。这时候,类加载器ClassLoader会将这些类,以及该java文件import的类加载到JVM中的方法区。这些被加载的类的类型都是Class,习惯称之为类对象。code
对象的建立,便是根据这些Class类对象,在堆区建立对象。对象
这时候,反射就很好理解了。反射的目的就是获取这些Class类对象blog
目前我知道能够利用反射返回类对象的方式有四种:继承
1.若是你知道类的路径:接口
Class aclass = Class.forName("类的路径"); //如java.util.ArrayList,你就能够得到ArrayList的类对象
2.若是你知道类:get
Class aclass = ArrayList.class;
3.若是你实例化对象:编译器
ArrayList<Integer> array = new ArrayList<Integer>(); Class aclass = array.getClass();
4.经过类加载器加载(我的不常常用忘记了hhh)博客
得到Class类对象,咱们能够很是轻松的获取到该类的字段和方法,咱们甚至能够获得该类的父类:如:getMethod,getConstructor...
就是获取类对象的方法,构造器等等,这些能够去网上查到相应的资料,这里不作赘述。
咱们获得了Class类对象,咱们就能够利用Class类对象建立一个对象实例了!这里就是工厂模式的利用方法,将全部类建立的工做交给工厂类实现,并将建立的对象返回便可。这样就能方便管理对象建立的工做。利用反射,建立对象的例子:
//利用反射机制建立一个ArrayList的对象 Class aclass = Class.forName("java.util.ArrayList"); //依靠反射,获取ArrayList的类对象 ArrayList<Integer> array = (ArrayList<Integer>)aclass.newInstance(); //利用Class类对象,建立ArrayList类
以前我也不知道什么是静态加载,什么是动态加载,看了一我的的博客豁然开朗:博客链接
他说的很清楚了:java中的new方法是静态加载,由于new方法是在编译阶段就会检查,而不是在运行阶段。反射是能够在运行时建立对象,调用对象的方法、变量等。
该博客做者利用了两个例子进行诠释
静态加载:
//定义接口 interface OfficeAble{ public void start(); } //Main class Office{ public static void main(String[] args){ if(args[0].equals("Word")){ Word w = new Word(); w.start(); } if(args[0].equals("Excel")){ Excel e = new Excel(); e.start(); } } //Word类 class Word implements officeAble{ public void start(){ System.out.println("Word Start"); }
这样会报错。静态加载会在编译阶段将Class类对象加载进方法区,由于这里没有定义Excel类,编译器就会报错。
动态加载:
//接口和Word类同上,修改一下Main方法 class Office{ public static void main(String[] args){ try{ Class c = Class.forName(args[0]); OfficeAble oa = (OfficeAble)c.newInstance(); oa.start(); } catch(Exception e){ e.printStackTrace(); } }
这样就能成功运行,利用反射,只要知道接口,能很好的提升扩展性!无论写多少个类,只要继承接口,均可调用。