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