反射,可不只是利用Class创建对象哟,更重要是替对象执行方法!关于反射创建对象,它可以提供一种通用的机制,对任意Class对象得到它的实例,而不需要import。
举个例子,Spring底层就是利用反射为我们工程中的类创建实例,但Spring内部可从来没有import我们的类(事实上也不可能,世界上用Spring的工程何其多!)。
这是一种运行时创建实例的机制,可以摆脱编译依赖带来的限制,提供一种更为通用的对象创建途径。
但反射除了替类创建实例外,还有一个更为重要的能力:替对象执行方法!相比“替类创建实例”,“替对象执行方法”更能体现“反射”中“反”这个字的内涵。作为一门面向对象语言,Java的对象职责可以简略说成:封装数据和行为。而方法作为一种行为描述,是所有对象共有的,不属于某个对象独有。比如现有两个Person实例:
Person p1 = new Person(); Person p2 = new Person();
假设Person有两个字段 name、age,有一个方法:changeUser()
对象 p1保存了"hst"和18,p2保存了"cxy"和20,但是不管是p1还是p2,都会有changeUser(),而每个对象里面写一份太浪费。
既然是共性行为,可以抽取出来,放在方法区共用。但这又产生了一个棘手的问题,方法是共用的,JVM如何保证p1调用changeUser()时,changeUser()不会跑去把p2的数据改掉呢?
为了解决这个问题,Java设计了一种隐性机制,每次对象调用方法时,都会隐性传递当前调用该方法的对象参数,方法可以根据这个对象参数知道当前调用本方法的是哪个对象!
同样的,在反射调用方法时,本质还是希望方法处理数据,所以必须告诉它去处理哪个对象的数据。
反射API中,有个Method对象,它就像一个方法执行器,当你想要执行某个对象的某个方法时,根本不要求这个对象本身,而是去找到Method,告诉它:帮我找到老默,告诉他我想......
啊不,说错了,应该是:找到Method,把对象+参数告诉它,Method帮你执行。
这就像什么呢?有一个老师傅,一直不肯使出本门剑法的最后一招。正常来说,你要求他:师傅,请你调用一下剑法的最后一招让徒孙开开眼吧!
现在有了反射,你就不用求他了,直接找到Method,把师傅绑了,并且找到师傅的剑,人和剑一块儿都塞给Method,然后Method催动内力,逼着师傅拿着剑把最后一招耍出来了。