首先,在了解java的反射的时候,我们应该先提出几个问题,
第一,什么是java的反射机制?
第二,java反射机制的功能是什么?
第三,为什么要用java的反射机制?
第四,java的反射机制是如何实现的,实现的过程是什么样子的?
通过这四个问题,我们一点点如了解java的反射机制。
第一个问题:
java的反射机制是在运行状态,对任意一个类,能够知道这个类的所有属性和方法,对任意一个对象都能够调用它的任意方法和属性。这种动态调获取信息以及动态调用对象的方法功能就是java语言的反射机制。或者说就是加载一个运行时才知道的类以及他的完整内部结构。举个小栗子。
package com.sohu.action; public class TestModel { String name="我是成员变量!"; /** * 构造函数 */ public TestModel(){ System.out.println("----我是构造函数!----"); } /** * 静态代码块 */ static{ System.out.println("---我是静态代码块-----"); } { System.out.println("----我是非静态代码块----"); } public void method(){ System.out.println("---我是局部方法---"); } }
编写测试类:
public class Test3 { public static void main(String[] args) { try { //测试类名.class Class testModel=TestModel.class; System.out.println("获取包名===>"+testModel.getPackage()); System.out.println("获取类的全路径===>"+testModel.getName()); System.out.println("获取类名===>"+testModel.getSimpleName()); Method[] methods = testModel.getMethods(); for(Method method:methods){ System.out.println("===获取方法===="+method.getName()); } } catch (Exception e) { e.printStackTrace(); } } }
上面的输出如下:
获取包名===>package com.sohu.action 获取类的全路径===>com.sohu.action.TestModel 获取类名===>TestModel ===获取方法====method ===获取方法====wait ===获取方法====wait ===获取方法====wait ===获取方法====hashCode ===获取方法====getClass ===获取方法====equals ===获取方法====toString ===获取方法====notify ===获取方法====notifyAll
这里的(类名).class就是反射。这里获取Class对象,还有两种方法:new (类).getClass()和Class.forName("类的全路径"),这个以后再细说。
通过上面的例子,我们可以看出,java的反射机制是可以获取运行时才知的类的方法和属性,其他的测试大家可以自己去做一下。这里的
现在来看第二个问题:
java反射提供的功能:
1.在运行时判断任意一个对象所属的类;
2.在运行时构建任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法;
以上四个在参考上面的例子进行理解;要注意,这四个都是在运行时而不是编译时进行的,也就是说在运行时不知道哪个类,通过反射实现了我们想要的。
5.生成动态代理。
然后我们来看,为什么要用反射机制;
首先,java的反射可以使代码更加灵活,更加容易实现面向对象。
期次就是java反射可以解藕。
对于最后一个问题,也还是浅显的用例子来说明一下,对于java的反射机制也只能起到一定理解作用,在深入还需要更加努力的去了解。
例如有这样的情况,我们有多个实体类,每个实体类中的属性都不一样,不会重复,我们要获取其中的某些属性,这些属性不在同一个实体类中,该如何去实现。直接上代码
package com.sohu.action; import java.lang.reflect.Method; import java.util.List; /** * 封装联合实体类的方法 * 利用java的反射类method * @author HBL1 * */ public class ModelUtils { //需要一个List放置实体类 List<Object> list=null; /** * 构造函数,进行赋值 * @param list */ public ModelUtils(List<Object> list){ this.list=list; } /** * 获取属性的值 * @param fName 获取联合实体类的属性的名称 * @return */ public <T> T getValue(String fName){ //组装方法名,这步是为了在调用此方法时直接进行参数传递就行,不需要传方法名称 String methodName="get"+fName.substring(0,1).toUpperCase()+fName.substring(1); //获取方法名所在的实体类 for(Object o:list){ try { //查找方法,查找还有一个无参数的方法,单能传方法就尽量传,提高反射效率 Method method = o.getClass().getMethod(methodName); //判断方法是否存在 if(method!=null){ //由于invoke返回的是Object类型,因此要强制转换成T类型 return (T)method.invoke(o); } } catch (Exception e) { } } return null; } public <T> void setValue(String fName,T value,Class<T> type){ String methodName="set"+fName.substring(0,1).toUpperCase()+fName.substring(1); for(Object o:list){ try { //查找方法 Method method = o.getClass().getMethod(methodName,type); if(method!=null){ method.invoke(o, value); return; } } catch (Exception e) { } } } }然后我们测试一下利用反射封装的类如何实现我们想要的,在这里实体类就不上传了。
package com.sohu.action; import java.util.ArrayList; import java.util.List; import utils.system; import flex.cc.baseInfo.model.GBankaccount; import flex.cc.baseInfo.model.GInsurer; public class Test2 { public static void main(String[] args) { List<Object> list =new ArrayList<Object>(); list.add(new GBankaccount()); list.add(new GInsurer()); FieldsUtils fieldsUtils=new FieldsUtils(list); String name="fparentid";//这个是你要获取的属性值 String value="我是测试数据"; fieldsUtils.setValue(name, value); System.out.println(fieldsUtils.getValue(name)); } }
打印的结果如下:
我是测试数据获取到了我们想要的数据。
对于java反射还在进一步理解中,有许多不足之处还请多指教,