1. 首先理解什么是反射?
反射(Reflection)能够让运行于 JVM 中的程序检测和修改运行时的行为。
2. 为什么需要反射?
反射能够让我们:
- 在运行时检测对象的类型;
- 动态构造某个类的对象;
- 检测类的属性和方法;
- 任意调用对象的方法;
- 修改构造函数、方法、属性的可见性等;
3.Class 类实例对象的方法
Class 实例对象的三种方法:
a. 通过类的隐含的静态成员 class;
b. 通过该类的 getClass() 方法;
c. 通过类的全称,用 Class.forName(“ 类名”) 获取。
以上三种方法可以参考下面的代码:
- class ClassDemo0{
- public static void main(String[] args) {
- Foo foo1=new Foo();
- //a, 任何一个类都有一个隐含的静态成员 class
- Class c1=Foo.class;
- //b, 已知该类,通过 getClass 方法
- Class c2=foo1.getClass();
- //注 c1,c2 表示 Foo 类的类类型(class type)
- System.out.println(c1==c2); //true, 一个类只可能是 Class 类的一个实例对象
- //c, 通过类的全称获取
- Class c3=null;
- try{
- c3=Class.forName("Foo");
- }catch(ClassNotFoundException e){
- e.printStackTrace();
- }
- System.out.println(c2==c3);//true
- //通过类的类类型创建该类的对象实例,通过 c1,c2,c3 创建 Foo 的对象实例
- try{
- Foo foo=(Foo)c1.newInstance();//前提:该类要有无参构造函数
- }catch(InstantiationException e){
- e.printStackTrace();
- }catch(IllegalAccessException e){
- e.printStackTrace();
- }
- }
- }
- class Foo{
- void print(){
- System.out.println("Foo");
- }
- }
4. 动态加载类
首先我们要了解:为什么要动态加载?
当我们编写一个程序的时候,我们首先要编写代码,然后进行编译,编译通过之后才可以运行。
然后我们要清楚,当我们使用 new 的方式来创建一个对象的时候 [ new Book() ],Book 这个类就要被静态加载。
(编译时刻加载的类是静态加载类,运行时刻加载的类是动态加载类)
现在,我们假设有这么一段代码:
- class Office{
- public static void main(String[] args) {
- //new 创建对象 是静态加载类,在编译时刻就需要加载所有的可能使用到的类,(若没有建 Word 类),编译不通过
- //若有建 Word 类,但 Excel 类没建,但编译还是不能通过
- //希望用到时再加载,可以通过动态加载类实现
- if("Word".equals(args[0])){
- Word w=new Word();
- w.start();
- }
- if("Excel".equals(args[0])){
- Excel e=new Excel();
- e.start();
- }
- }
- }
再假设 Word 这个类是存在的,那么 new Word() 这句话编译是可以通过的。
但是如果 Excel 这个类不存在,那么编译就会报错,编译不通过,程序就不能运行。
也就是,因为一个类的错误,影响了整体程序的运行。
那么我们要避免这样的情况,应该怎么做呢?
在这种情况之下,就可以使用动态代理。
- class OfficeBetter{
- public static void main(String[] args) {
- try{
- //动态加载类,在运行时加载
- Class c=Class.forName(args[0]);
- //通过类类型,创建该类对象
- //Word w=(Word)c.newInstance(); //如果加载的是 Excel 呢?
- //Excel e=(Excel)c.newInstance(); //如果加载的是 Excel 呢?
- //后期增加功能就不用改动 OfficeBetter,实现在线升级,扩展性更强
- OfficeAble oa=(OfficeAble)c.newInstance(); //所以做一个标准————功能型的类尽量使用动态加载
- oa.start();
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
- interface OfficeAble{
- public void start();
- }
- class Word implements OfficeAble{
- public void start(){
- System.out.println("word...start...");
- }
- }
- class Excel implements OfficeAble{
- public void start(){
- System.out.println("Excel...start...");
- }
- }
可以看到,正常情况下,如果需要在 officeBetter 这个类中通过 new 的方式将我们可能用到的所有的类都实例化出来。
这样不仅占用了内存,同时也存在如果一个出现错误其他的也不能运行这样的问题。
而我们现在通过一个借口,让子类去继承,然后我们通过获得传递过来的 class,创建出该类的对象,这个对象就是子类的对象了。
在这种情况下,如果有新增或者减少功能(比如在旧的方法的情况下要添加一个 pencil),就不需要对这个类进行修改,只需要新建新的类就可以了。
转载请注明:热爱改变生活.cn » 反射的介绍以及动态加载类——反射_1
本博客只要没有注明“转”,那么均为原创。 转载请注明链接:sumile.cn » 反射的介绍以及动态加载类——反射_1