1. 什么是反射?
反射是java的一种特性,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的四种创建对象方式
-
以
对象.getClass()
的形式获取对象Person person=new Student(); Class person1 = person.getClass();
-
通过
Class.forName()
创建反射获取对象Class person2 = Class.forName("com.xuan.反射.Student");
-
通过
类名.class
创建反射获取对象Class <Student> person3 = Student.class;
-
通过类加载器获取对象
ClassLoader cl = this.getClass.getClassLoader(); // 使用当前类的ClassLoader Class clazz = cl.loadClass("com.rain.B") // 使用第一步得到的ClassLoader来载入B B b = (B)clazz .newInstance(); // 有B的类得到一个B的实例
2. 反射与new的区别
- 反射和new都是创建对象实例的,但是new对象无法调用该类里面私有
private
的属性,而反射可以调用类中private
的属性! - new属于静态编译。就是在编译的时候把所有的模块都确定,如果有添加或删除某些功能,需要重新编译。但系统不可能一次就把把它设计得很完美,当发现需要更新某些功能时,采用静态编译的话,需要把整个程序重新编译一次才可以实现功能的更新。也就是说,用户需要把以前的软件卸载了,再重新安装才会重新编译!这样的系统耦合严重,难以扩展!
- 反射属于动态编译。在运行时确定类型并创建对象,通过反射指定模板,动态的向模板中传入要实例化的对象。动态编译最大限度发挥了Java的灵活性,体现了多态的应用,有以降低类之间的藕合性。其中
spring
中ioc
的核心就是利用了反射解耦合。 - 反射效率较低,但经过jdk很多版本的优化,效率已经很高了!
2. IOC为什么要使用 工厂 + 反射 创建对象?
Spring中的IoC的实现原理就是工厂模式加反射机制。 如果工厂模式中不使用反射,而使用new创建对象:
//接口 fruit
interface fruit{
public abstract void eat();
}
//实现类 Apple
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
//实现类 Orange
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
//构造工厂类
//也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}
上面写法的缺点是当我们再添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改动就会很多。下面用反射机制实现工厂模式:
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
class Factory{
public static fruit getInstance(String ClassName){
fruit f=null;
try{
//工厂中使用反射!
f=(fruit)Class.forName(ClassName).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Reflect.Apple");
if(f!=null){
f.eat();
}
}
}
这样使用反射的方式,无论我们创建多少fruit
的实例,都不需要修改反射生成的工厂模板,有效的降低了系统耦合性!
IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言提供的反射机制,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。