浅析java的反射机制

1、JAVA反射机制是指,在程序运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。之所以能做到这一点,靠的是java中Class类,该类是用于描述字节码文件的类,通过该类的实例化对象可以得到该对象所表示的类的所有信息,包括类中的构造器,字段,以及类方法。因此简单来说,反射机制可以理解成是对类的解剖。反射机制的作用是提高程序的扩展性和灵活性,使得程序可以便捷地增加或者修改功能。

2、我们以电脑主板的功能扩展为例来说明反射机制的实际应用,体会它带来的便捷性。首先创建一个MainBoard类,该类表示电脑主板

public class MainBoard {
	public void run(){
		System.out.println("mainboard run");
	}
	public void usePCI(PCI pci){
		if(pci!=null){
			pci.open();
			pci.close();
		}
	}
}
该类中有两个方法,run()表示使用主板的本身功能,usePCI()表示使用主板上插件的功能,该方法的参数便是一个插件对象。为了可以使用各种各样的插件,可以定义一个接口PCI,这样一来,只要某个插件实现PCI接口,那么该插件就可以被该主板所使用。(ps:这里也体现了java中的多态)

public interface PCI {
	public void open();
	public void close();
}
接下来我们就可以为该主板增加插件了,创建SoundCard类,表示声卡

//该类用于模拟声卡,要将其插在主板上,扩展主板的功能
public class SoundCard implements PCI{

	@Override
	public void open() {
		System.out.println("soundcard open...");
	}

	@Override
	public void close() {
		System.out.println("soundcard close...");
	}
	
}
创建主函数,运行主板

public class ReflectApp {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws Exception 
	 */
	//以电脑主板的功能扩展为例演示反射机制的应用,体现其强大的扩展性
	public static void main(String[] args) throws IOException, Exception {
		MainBoard mb = new MainBoard();
		mb.run();
		//读取配置文件,获得插件信息
		Properties prop = new Properties();
		File file = new File("pci.properties");
		FileReader fileReader = new FileReader(file);
		prop.load(fileReader);
		
		//加载配置文件中所写的类,对配置文件所写的插件类进行实例化,以此来使用插件的功能
		for (int i = 0; i < prop.size(); i++) {
			String key = "pci"+(i+1);
			Class clazz = Class.forName(prop.getProperty(key));
			PCI pci = (PCI) clazz.newInstance();
			mb.usePCI(pci);
		}	
	}
}
在主函数中调用主板的usePCI()方法时,需要传入一个具体的参数,也是说要指定具体的插件对象,这样做的弊端是:当我们以后想要使用其它插件或者增加插件时,就需要到源代码中修改方法的参数,将其替换成其它的插件。能不能不修改源代码就可以更换插件或者增加插件呢?反射机制便可以解决这个问题。因为它可以实现对象的动态获取,在这个例子中就是实现插件对象的动态获取,也就是说我们在程序运行时才指定具体使用哪个插件。那么如何来指定使用哪个插件呢?这需要我们来为程序写一个配置文件pci.properties,配置文件中的内容以键值对的形式给出,标明程序中要使用的插件类的名字。(ps:如果该类有包名,一定要加上包名)

pci1=SoundCard
这样一来,在程序运行时读取该配置文件,便可以拿到要使用的插件类的类名,一旦知道了类名,便可以通过Class类拿到该插件的实例化对象。这样便实现了对象的动态获取。如果想要更换插件或者增加插件,只需要修改配置文件即可,而无需修改源代码。

比如:我想增加一个网卡插件,那么只需创建一个网卡类,并在配置文件中增加一条配置信息即可

public class NetCard implements PCI {

	@Override
	public void open() {
		System.out.println("netcard open");
	}

	@Override
	public void close() {
		System.out.println("netcard close");
	}

}
修改配置文件

pci1=SoundCard
pci2=NetCard




猜你喜欢

转载自blog.csdn.net/it_gjw/article/details/53196786