对反射的理解

JAVA中的反射是运行中的程序检查自己和软件运行环境的能力,它可以根据它发现的情况进行改变。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。

首先我们先明确两个概念,静态编译和动态编译。

静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

由定义我们可以看出动态编译的好处,而反射就是运用了动态编译创建对象。往往对比能更加直观的向我们展示两者的不同。

具体代码体现:
不用反射的代码是这样的:

public interface Fruit {  
    void eat();
}
public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃苹果.......");
    }
}
public class Banana implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃香蕉.......");
    }
}
//水果工厂类, 生产水果
public class FruitFactory {
//根据水果名 ,得到水果对象
public static Fruit getInstance(String fname) {
Fruit f = null;
if("apple".equals(fname)) {
            f = new Apple();
  }
if("banana".equals(fname)) {
            f = new Banana();
  }
return f;
}
}

public class TestFruit {   
public static void main(String[] args) {  
 //根据水果工厂生产出1种水果      
  Fruit f = FruitFactory.getInstance("apple");      
   f.eat();    
   }
   }

可以发现,每当我们要添加一种新的水果的时候,我们将不得不改变Factory中的源码,而往往改变原有正确代码是一种十分危险的行为。而且随着水果种类的增加,你会发现你的factory类会越来越臃肿,不得不说这是一种比较low的做法。(初学者可能会问,为什么不直接在main方法中new水果,这是因为我们可能会在getInstance方法中做一些别的事情。。。所以不直接new)
使用反射的代码及优势(除了工厂类和测试类需要改变) 其他不用更换

17 1public class FruitFactory {
   /**    * 根据水果名 ,得到水果对象
public static Fruit getInstance(String className) {     
 Fruit f = null;      
 try {           
  //根据传入的类名 得到 水果对象 -- 是一种聪明的做法           
   f = (Fruit) Class.forName(className).newInstance();    
   } catch (Exception e) {            
   e.printStackTrace();     
   }   
   return f;
   }
   }
  public class TestFruit {  
  public static void main(String[] args) {      
   //根据水果工厂生产出1种水果       
    Fruit f = FruitFactory.getInstance("com.hp.reflex.Orange");        
    f.eat();    
    }
    }

在出现新品种水果的时候,完全不用去修改原有代码。从上面的案例中,我们可以清楚的体会到反射的优越性。

那么有的人又会问,这个例子能完全明白,但是如果放到实际的编程,应用中,我们又会在什么情况下用到反射那?

举一个看到过的例子,在实际开发中,我们需要把一个包中的class new出来,但是这个包中的类总是需要变动,那么怎么办,难道总是修改main方法中xxx=new xxx()吗。这样无疑是麻烦的。而运用反射。

我们可以相应的增加一个配置文件,在里面记录包中所有的类名,包中类增加时就加一个类名,删除时就删除一个类名。让main方法去读取这个配置文件中的类名,通过反射获得实例,完全不用我们去修改main方法中的代码。(Spring的IOC就是这个原理)

他甚至可以修改其他类中的私有属性。android开发中,我们需要改变一个私有标志位的时候,android源码并没有提供set方法,我们又不能改变源码,怎么办,反射可以完美解决这个问题。