在最刚开始接触设计模式的时候,那时候还是用的vb.net,对于反射只是懵懵懂懂,只知道把dll放到指定地方,就可以通过Assembly加载并获取里面的类。对于那个阶段的反射,只是停留在了类的层次。
后来,学习了JavaScript,这门脚本语言,是弱类型、基于面向对象的(到现在依然还是懵懵懂懂)。这个里面的反射,确切的说,JavaScript没有完整的反射体系。但是在编码中可以通过代码设计来完成类似反射的基本功能。还是比较简单的吧。
再后来,就是现在了,接触了Java的反射。可以说真正接触反射,就是从这里开始的。
说到底,反射到底是什么?我们来看看百度百科怎么说:程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。Java不是动态语言,但Java有非常突出的动态相关机制,可以加载一个运行时才知名称的class,获悉其完整构造,并生成其对象实体、或对其fields设值、或唤起其methods。
而对fields、methods的使用可以遍历,可以通过字符串进行指定,这也就使得不同类,可以调用相同的方法。例如:我现在有一个方法,接收一个Object类型的参数,我确定传进来的Object都会有一个Id的属性,我要获取这个属性,并对其进一步操作。
现在该怎么办?在学了今天这篇博文后,你可以用commons-beanutils.jar包里面的BeanUtils和PropertyUtils工具类。
这个方法,只能获取到指定类自身内部的属性,对于父类里面的属性,是获取不到的
public Object getFieldValue(Object object, String propertyName) throws IllegalAccessException, NoSuchFieldException { //获取Object的指定property Field field = object.getClass().getDeclaredField(propertyName); //设置其可见性,若不设置,则无法获取其值,如果获取的属性为public,则可以不加这句 field.setAccessible(true); return field.get(object); }更多的时候,如果说传入的Object都会有,那么我们一般考虑将其抽象到父类里,那么上面的方法就不适合了。下面这个方法,可以获取自身及父类里面的所有属性,思路其实很简单,就是在当前类里面获取该字段,如果没有,就去其父类里面获取:
public Object getFieldValueInAllSuper(Object object, String propertyName) throws IllegalAccessException, NoSuchFieldException { //获取当前Object的class Class claszz=object.getClass(); Field field = null; do{ try{ //从类里面获取指定属性 field = claszz.getDeclaredField(propertyName); } catch(NoSuchFieldException e){//如果没有获取到,则设置为null field=null; } //设置当前class为父class claszz=claszz.getSuperclass(); } while(field==null&&claszz!=null); //当field为空且class不为空时,进行下次循环 //如果field为空,说明没有此字段,返回空 if(field==null) return null; //如果不为空,设置可见性,然后返回 field.setAccessible(true); return field.get(object); }
private String getId(Object o) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { //从当前类及父类中找 return (String) o.getClass().getMethod("getId").invoke(o); //只查找当前类 return (String)o.getClass().getDeclaredMethod("getId").invoke(o); }
属性、方法反射完了,那么应该怎样去动态的加载一个类呢?这里就只提一下:用Class.forName()。其实我感觉这里用的比较多的是传入接口类型,然后获取接口的class当作参数。
最近这些日子,对于泛型、反射用的比以前多了很多,也体会到了它们的用处。最近的博客,应该都会和这些有关,因为封装,如果离了这两个,真心感觉那将是恶梦~~