Reflection(反射)是Java被视为动态语言的关键,反射机制容许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操做任意对象的内部属性及方法。数组
Java反射机制主要提供了如下功能:框架
一、在运行时构造任意一个类的对象spa
二、在运行时获取任意一个类所具备的成员变量和方法代理
三、在运行时调用任意一个对象的方法(属性)对象
四、生成动态代理继承
咱们通常是经过某一个类的 Class类的实例来进行获取某一个类中的方法以下代码:get
Class clazz = Class.forName(“全类名”);源码
Method[] methods = clazz. getDeclaredMethods(); io
Class 对象获取 Method 的方法:class
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getMethod(String name, Class<?>... parameterTypes)
Method[] getMethods()
其中getMethod 、getMethods只能获取本类及从父类中继承过来的公有方法,而getDeclaredMethod、getDeclaredMethods 只能够获取本类中定义的方法(包括私有方法)!其中getDeclaredMethod 、getDeclaredMethods 较为经常使用!
那么当咱们获取到某一个类中的方法时,咱们怎么来进行执行该方法呢?
Method 对象的方法:
Object invoke(Object obj, Object... args)
其中该方法的第一个参数是类哪个对象来调用方法,第二个参数是方法中有哪些参数!
咱们通常是经过Method 对象调用 invoke() 方法,来进行执行相关方法。
同理对于某一个类中的字段咱们也能够经过反射来获取!其获取的方法以下代码:
Class clazz = Class.forName(“全类名”);
Field[] fields = clazz. getDeclaredFields();
Class 对象获取 Field 的方法:
Field getDeclaredField(String name)
Field[] getDeclaredFields()
Field getField(String name)
Field[] getFields()
其中getField 、getFields只能获取本类及从父类中继承过来的公有字段,而getDeclaredField、getDeclaredFields 只能够获取本类中定义的字段(包括私有字段)!
一样咱们也能够为字段进行设置和获取字段的值
Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。
void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
具体能够参看 Java API。
以下咱们结合着代码来看一下泛型和反射(到后期咱们使用框架时,咱们看它们的源码时就会发现有大量的反射与泛型结合的代码)!
以下代码:
JavaBean:
public class Person{
//私有属性。
//相应的getting和setting方法。
//空构造器(利用反射建立对象时进行调用来使用)。
}
泛型类:
public class Dao<T>{
public T select(int id ){
// 就不写方法的实现了,直接return null了,就不返回T类型的对象了!
return null;
}
}
继承泛型的相关类:
public class PersonDao extends Dao<Person>{
// ... ...
}
public class Test{
public static viod main(String[] args){
PersonDao pDao = new PersonDao();
Person person = pDao.select(1);//如何来返回Person类型的对象?
}
}
此时对于咱们来讲咱们不进行建立对象,交由反射来为咱们进行建立返回的 T 类型对象(在此处建立的返回类型应该是Person类型的对象) ,对于泛型而言咱们知道其不能使用 .class 属性!那这样怎么返回 T 类型(Person类型)的对象呢?在此咱们可以获取继承泛型类 Dao<T> 的PersonDao类的 Class 类型的对象,咱们可使用Class clazz = Class.forName(“全类名”); 来获取PersonDao的Class 类型的对象, 而后经过使用Type getGenericSuperclass()获得带泛型类型的父类的Type类型的对象,即获得Dao<T> :Dao<Person>。此时已经将T类型实例化为Person类型了,通常咱们还须要判断一下其是不是带类型参数的类型ParameterizedType,经过if( type instanceof ParameterizedType)来判断,若是是而后经过ParameterizedType getActualTypeArguments() 方法获取到实际的泛型类型参数数组。即获取到 Person类型的Class 实例。进而经过是newInstance() 方法获得 Person类型的对象。进而返回!
能够参考下面的代码进行理解:
public static Class<?> getActualTypeArgumentsByGenericSuperclass(Class<?> clazz, int index) {
Type genericSuperclass = clazz.getGenericSuperclass();
//判断其是不是带类型参数的类型
if (!(genericSuperclass instanceof ParameterizedType)) {
return Object.class;
}
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
//获取到实际的泛型类型参数数组.
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (index > actualTypeArguments.length-1|| index<0) {
return Object.class;
}
if (!(actualTypeArguments[index] instanceof Class)) {
return Object.class;
}
return (Class<?>) actualTypeArguments[index];
}