反射机制,就是指程序可以获得自己的属性和方法。java中,只要知道类的名字,就可以通过反射机制获取类的所有属性以及方法
java中的反射机制,主要靠Class类实现,java.lang.Class是一个特殊的类,用于封装jvm中加载的类对象的信息,每个类加载后都会对应生成一个Class对象,可以通过类名获取该对象的属性、方法,甚至创建该对象
如果想要获得对象信息,或者对象方法,亦或是创建对象,那我们直接new对象不就好了,干嘛要使用反射机制呢?这涉及到静态编译和动态编译的问题,我们都知道,java是一种先编译后运行的语言,区别就在编译方式上:
编译时绑定对象,确定类型,程序在运行时直接加载对象,不必再编译
运行时确定类型,绑定对象,程序运行时用到该对象才会编译再加载,更加灵活
反射使用的方式就是动态编译,在运行时创建对象,运行时访问对象属性和方法,他有以下几个好处
由于运行时比静态编译多了一次编译过程,所以运行效率必然会不如静态编译直接使用对象的功能或方法,但是最近版本中,这个速度差别已经被降低到1-2倍
Spring IOC就是靠工厂模式+反射实现的,体现了五大设计原则中的依赖倒置原则,开闭原则,里式替换原则,如果对这几个原则不太熟悉的,可以看一下我的另一篇博客:java面向对象五大原则.结合这几个原则就可以发现Spring IOC的优美之处
//首先定义一个接口类
public interface human {
public void eat();
}
// 然后实现男女类继承该接口类
public class man implements human{
@Override
public void eat() {
System.out.println("男人的吃法");
}
}
public class woman implements human{
@Override
public void eat() {
System.out.println("女人的吃法");
}
}
//最后实现工厂类
public class humanFactory {
public human getInstance(String objectname){
if(objectname.equals("man")){
return new man();
}else if(objectname.equals("woman")){
return new woman();
}else{
return null;
}
}
}
这里可以看见,我们使用工厂管理对象的创建,但是有一个问题,每次要增加类的话都要去修改工厂,岂不是很麻烦,因此我们使用反射的方法重新实现一下
//首先定义一个接口类
public interface human {
public void eat();
}
// 然后实现男女类继承该接口类
public class man implements human{
@Override
public void eat() {
System.out.println("男人的吃法");
}
}
public class woman implements human{
@Override
public void eat() {
System.out.println("女人的吃法");
}
}
//最后实现工厂类
public class humanFactoryReflect {
public human getInstance(String objectname) {
human human = null;
try {
human = (human) Class.forName(objectname).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return human;
}
}
可以看到,我们使用反射机制后,如果需要扩展human的种类,就不再需要修改工厂模式,而是只需要继续增加需要的类实现接口,只需要知道类的权限定名就可以通过工厂创建对象,优美地满足了开闭原则
首先创建一个human的配置文件,human.porperties
man=com.springIOC.man
woman=com.springIOC.woman
//首先定义一个接口类
public interface human {
public void eat();
}
// 然后实现男女类继承该接口类
public class man implements human{
@Override
public void eat() {
System.out.println("男人的吃法");
}
}
public class woman implements human{
@Override
public void eat() {
System.out.println("女人的吃法");
}
}
//操作属性文件类
class init{
public static Properties getPro() throws FileNotFoundException, IOException{
Properties pro=new Properties();
File f=new File("human.properties");
if(f.exists()){
pro.load(new FileInputStream(f));
}else{
pro.setProperty("man", "com.springIOC.man");
pro.setProperty("woman", "com.springIOC.man");
pro.store(new FileOutputStream(f), "FRUIT CLASS");
}
return pro;
}
}
//最后实现工厂类
public class humanFactoryReflect {
public human getInstance(String objectname) {
human human = null;
try {
human = (human) Class.forName(objectname).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return human;
}
}
有了配置文件后,我们可以通过配置文件的属性,避免写权限定名的麻烦,spring ioc就是使用了这种方式