反射的定义:指程序运行期间,能够观察类的属性和方法、以及修改类的对象的属性和行为的特征。
也可以理解为:动态的获取和修改类的机制。
反射区别与new,new是静态获取类,而反射是动态。在性能上,动态差于静态。因为new是可以直接确定new哪一个对象,而
反射确定哪一类的对象需要一个反射验证的过程。
静态:把类都编写好,编译通过,进行运行。
动态:类都编写好,也能运行,在运行期间动态获取类的信息、修改类的属性。
反射最大的应用是框架,spring中一切都是反射,struts、Hibernate都是通过类的反射开发的。
最常见的应用场景:
1.使用jdbc链接数据库
2.servlet在web容器中的加载和运行。
当然这些理解比较抽象,下面列举一个示例,便于理解。
一个项目在运行中,需要对一些优惠方案进行调整,但是项目不能停止运行,需要在ABC三个优惠方案中选择。
/**
* 公共优惠方案父类
*/
public class YouhuiFather {
public void test(){
System.out.println("我是公共的优惠方案父类!");
}
}
/**
* 优惠方案A
*/
public class YouhuiA extends YouhuiFather{
public void test(){
System.out.println("我是公共的优惠方案A");
}
}
/**
* 优惠方案B
*/
public class YouhuiB extends YouhuiFather{
public void test(){
System.out.println("我是公共的优惠方案B");
}
}
/**
* 优惠方案C
*/
public class YouhuiC extends YouhuiFather{
public void test(){
System.out.println("我是公共的优惠方案C");
}
}
fanan.properties 是优惠方案配置文件,用于调整选择ABC方案
fangan=model.YouhuiB
/**
* 读取优惠方案的类
*/
public class Factory {
private String fangan;//配置文件key
/**
* 获取选择优惠方案
*/
public Object chooseYouhui() throws Exception{
Properties properties=new Properties();
String fileName="fanan.properties";
//以流的方式读取配置文件
InputStream stream=Factory.class.getClassLoader().getResourceAsStream(fileName);
properties.load(stream);
fangan=properties.getProperty("fangan");//读取配置文件方案
//动态拿到优惠方案的实例,修改配置文件不需要项目重启
Object object=Class.forName(fangan).newInstance();
return object;
}
}
/**
* 调用优惠方案类
*/
public class Client {
private YouhuiFather youhui;//调用的方案
public Client(YouhuiFather youhui) {
this.youhui = youhui;
}
/**
* 调用优惠方案
*/
public void diaoyong(){
youhui.test();
}
/*传统方式利用new对象的方式来解决,用选择结构进行判断
如果是A方案就new一个A方案的对象,并调用A的优惠方案,以此类推
可以看出将是一大串的代码
特点是方便修改,只需要修改配置文件,方便运维人员修改*/
}
/**
* 测试类
*/
public class TestYouhui {
public static void main(String[] args) throws Exception {
Factory factory = new Factory();
try {
YouhuiFather youhui = (YouhuiFather) factory.chooseYouhui();
Client client = new Client(youhui);
client.diaoyong();//调用优惠
} catch (Exception e) {
e.printStackTrace();
}
}
}
这样,运维人员只需要修改配置文件就可以达到切换优惠方案的效果。而不需要像new对象那样写死?是不是跟jdbc链接池的配置很像呢?
那么上述代码反射的模式是否可以用new取代呢?当然是可以的,你可以发现核心类Factory获取配置文件
属性后,完全可以加一个选择结构来选择优惠方案,比如读取“youhuiC”,那么就new一个YouhuiC的对象返回。
一样是可以实现功能的。缺点有两点:
1.代码相比上面要臃肿很多。
2.不方便修改,如果增加一个D、F优惠方案呢?则逻辑代码也需要添加判断。当然你也可以反驳说这个在选择结构上
做文章,同样能被取代,因为我也想到了。好吧,代码的世界就是这么神奇,无穷无尽,但是反射的确够简单。