反射reflect
开发步骤
一 获得所要操作的类的文件字节码文件对象
方法一:利用Class类的forName()方法获取
方法二:通过类的静态.class属性来获取
方法三:通过类的getClass()方法来获取
二 有了这这文件的字节码文件,那么我们要创建该类的对象
对于无参的构造函数用newInstance()返回该类的一个对象
对于有参的构造函数用该类字节码文件的getConstructor()返回一个构造器对象(构造函数的类)然后用构造器的newInstance(参数)创建对象
三 现在我们要访问该类的成员变量
有了字节码文件对象啦,可以直接掉用clazz.getField("age")返回一个Field(变量)对象
用clazz.getDeclaredField(“age”)返回一个变量(Field)对象
四 访问与操作方法
一般方法的访问与调用
调用clazz.getMethod(“操作的方法名”,String.class,int.class(传入参数的类型))返回一个方法类对象Method
该对象调用的invoke(“上面创建的类对象”,“小强”,56)就可以掉用操作的类的上面指定的方法
对于私有的方法
操作和一般方法一样 只是将getMethod改成getDeclaredField 然后用的时候要先用setAccess强暴一下
静态方法
操作与一般方法一致,只是调用方法时不用传入对象
main方法
invoke(“要操作的类的对象”,(Object)Stirng【】{“abd”,“撒旦法”})
因为1.4版本时没有引入可变参数的概念,所以如果需要多个参数时就会用数组进行装载,而jdk在调用时会将这些数组中的元素拆分,
所以会将上面的String[]拆分成两个String 参数传入main方法,而程序并没有操作两个string参数的main方法所以会报错,
解决办法:将String强转成Object 让jdk误认为是传入一个对象,也就恰好达到我们想要传如多元素的数组的效果
还有一种解决:new Object【】{String【】{“abd”,“斯蒂芬”}}封装给虚拟机拆,也能拆到我们想要的结果
用途
框架的开发用到
如:我们可以定义一个接口
让接口具有某些方法或属性
然后在我们的框架里调用这些方法或属性
然而你却不知道别人会为你这个接口写一个什么样的名字的类
所以可以在框架中定义好反射机制
通过反射机制和配置文件相关联
只要在配置文件中告诉框架所调用的类名,方法,属性即可
反射机制会获取配置文件中的类名,方法名。。。。
不管别人写什么类,只要实现了接口的方法就可以在框架的程序中运行
例:就像Eclipse 自己没有图形化界面的操作,然而只要我们导入相应的包,Eclipse就能有相关的功能
内省(反射的特例)
开发步骤
一 调用getBeanInfo(Class<?> beanClass, Class<?> stopClass) 方法返回一个BeanInfo接口对象来省给进去的bean类,他会把bean的所有属性封装到beaninfo对象中,拿到这个beaninfo对象相当于拿到bean的所有属性
二 拿到这个beanifo对象后接着调用该对象的getPropertyDescriptors()就可以拿到每一个属性的属性描述器,该方法返回一个属性描述器数组PropertyDescriptor[]
三 拿到属性描述器后再调用该描述器的getReadMethod()就可以得到这个bean的get值
PropertyDescriptor pd = new PropertyDescriptor(“name”,Person.class);
Method method = pd.getWriteMethod()
method.invoke("P(创建要操作的对象)",“罗磊”);
用途:用于给Bean对象反射
开发现在多用BeanUtils
开发步骤
一,导包
导入beanutils 的jar包
而beanutils工作过程需要个日志记录器的支持,所以还需导入log4j中的Commons-logging。jar
然后直接调用BeanUtils.setproperty(“需要操作的bean的对象”,“需要操作的属性名”,“传入的值”);
由于beanutils 会自动将类型转为bean所需的类型,但这只能支持8种基本数据类型 |