对于反射的一些总结(二)

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];

       }

原文地址:https://www.cnblogs.com/Vincent-NMT/p/6083106.html