1. 反射(Reflection):
1.1. 接下来就让我们来聊一下什么叫反射?
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制主要提供了以下功能:
1、在运行时构造任意一个类的对象
2、在运行时获取任意一个类所具有的成员变量和方法
3、在运行时调用任意一个对象的方法(属性)
4、生成动态代理
1.2. 如何通过反射来获取任意一个类中所具有的方法?
我们一般是通过某一个类的 Class类的实例来进行获取某一个类中的方法如下代码:
Class clazz = Class.forName(“全类名”);
Method[] methods = clazz. getDeclaredMethods();
Class 对象获取 Method 的方法:
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() 方法,来进行执行相关方法。
1.3. 如何通过反射来获取某一个类中的字段?
同理对于某一个类中的字段我们也可以通过反射来获取!其获取的方法如下代码:
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。
1.4. 接下来进说一下关于泛型和反射!
如下我们结合着代码来看一下泛型和反射(到后期我们使用框架时,我们看它们的源码时就会发现有大量的反射与泛型结合的代码)!
如下代码:
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];
}