反射机制<二>
获取某一类的所有构造器:
明确操作的时哪一份字节码对象
1、 获取构造器 constructor类:表示类中构造器的类型,constructor的实例就是某一类中的某一个构造器
Public Constrcutor<?> getConstrcutor()只能获取公有(public 修饰)的构造器
Public Constrcutor<?> getDeclaredConstrcutor()获取所有的构造器方法,和访问权限无关
Public constructor<?> getConstrcutor(Class<?>… parammeterTypes);
参数:parammeterTypes表示:构造器参数的类型
调用构造器,创建对象:
Class c=string.class;
Constrcutor con=c.getDeclaredConstructor();
使用反射获取某一个类中的方法:
1、 找到获取方法所在类的字节码对象
2、 找到需要被获取的方法
Method[] getMethods(String name,Class<?>… parmeterType);获取所有public包括继承得到的方法
Method[] getDeclaredMethods(String name,Class<?>… parmeterType);获取不包括继承得到的所有方法(和访问权限无关)
使用反射调用方法:
1、 找到被调用方法所在的字节码
2、 获取到被调用的方法对象
3、 调用该方法
如何使用反射调用一个方法:
在Method类中有方法:
Public object invoke(object obj,object… args):表示调用当前Method所表示的方法
参数:obj:表示被调用方法底层所属对象
Args:表示调用方法是传递的实际参数
返回:底层方法的返回结果
调用私有方法之前应该设置该方法为可访问的
又因为Method是AccessibleObject子类,所有Method中具有该方法。
me.setAccessible(true)
反射很强大,但是耗性能(比直接慢差不多30多倍),主要是为了做工具和框架使用。
使用反射调用静态方法:
public Object invoke(Object obj,Object... args)
如果底层方法是静态的,那么可以忽略指定的obj参数。将obj参数设置为null.
使用反射调用可变参数的方法:
对于数组类型的引用类型的参数,底层会自动解包,为了解决该问题,我们使用Object的以为数组把实际参数包装起来。
以后使用反射调用invoke方法,在传递实际参数的时候,无论是基本上护具类型还是引用数据类型,也无论是可变参数
类型,反正就是一切实际参数参数都包装在new Object[]{}中,就没问题。
m.invoke(方法底层所属对象,new object[]{实际参数});通用
使用反射获取字段:
public Filed[] getFileds() 获取当前Class所表示类中的所有public的字段
,包括继承的字段
public Filed getFiled(String filedName)
public Filed getDeclaredFiled(String filedName)
public Filed[] getDeclaredFileds();获取当前Class所表示类中的所有字段
,不包括继承的字段
给某个类中的字段设置值和获取值:
1、找到被操作字段所在类的字节码
2、获取到该被操作的字段对象
3、设置值/获取值
Field set常用方法:
public void set(Object obj,xxx value);
public void setxx(Object obj,xxx value);
参数:
obj:表示字段底层所属对象,若该字段是static的,该值应该设为null
value:表示将要设置的值
Field get常用方法:
public xx getxx(Object obj);
public Object get(Object obj)
参数:
obj:表示字段底层所属对象,若该字段是static的,该值应该设为null
返回:
返回该字段的值
反射其他一些API
int getModifiers();获得修饰符
String getName()返回类的全限定名
Package getPackage()返回该类的包
String getSimpleName()获取类的简单名字
Class getSuperclass() 获取类的父类
boolean isArray() 判断Class实例是否是数组
boolean isEnum()判断该Class实例是否是枚举
使用反射调用一个泛型参数方法
获取泛型参数的信息
1、通过getGenericType方法获取到Type类型(该对象中包含了泛型信息)
2、把getGeneticType返回的类型强制转出ParameterizedType类型
3、调用ParameterizedType里的Type[] getActualTypeArguments()
4、Type[]中就保存了泛型信息
使用反射创建对象
如何编写工具类:
方式一:
1、把工具方法做成非static方法
2、把工具类做成单例模式的;
那么要调用工具方法,必须先得到工具类对象,再调用方法。
方式二:
1、把工具方法做成static方法;
2、把工具类所有的构造器全部私有化,或者把该工具类加上abstract的。
这个做的目的,就是为了全部是类去调用工具方法
如:java.util.Arrays