编程语言中的各种反射

        在最刚开始接触设计模式的时候,那时候还是用的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当作参数。

        最近这些日子,对于泛型、反射用的比以前多了很多,也体会到了它们的用处。最近的博客,应该都会和这些有关,因为封装,如果离了这两个,真心感觉那将是恶梦~~

编程语言中的各种反射

上一篇:js下载文件防止白屏


下一篇:(原创)发布一个c++11开发的轻量级的并行Task库TaskCpp