Java基础-反射

2021-01-27  本文已影响0人  森屿暖茶

反射是什么?

反射就是在运行状态中,对于任意的一个类,我们都能够知道这个类的所有属性和方法。对于任意一个对象都能调用他们任意的方法,并且能够改变它的属性。注意反射一定是在运行时。

反射的意义,如何使用。

一般情况下我们使用某个类就必须对这个类进行实例化,但是在某些情况下你无法实例化对象的时候,但是你又想对这个类进行相关操作。我们就需要使用JDK提供的反射的API来进行调用。Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:

   Field :可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段;

   Method :可以使用 invoke() 方法调用与 Method 对象关联的方法;

   Constructor :可以用 Constructor 的 newInstance() 创建新的对象。

JDK提供的反射API主要有以下实现帮助我们实现各种需求:

①在运行时,提供构造方法,能够使你实例化对象。

②在运行时,提供调用对象方法的方法。能够让你操作对象的方法。

③在运行时,提供获取和修改对象属性的方法。能够让你操作对象的属性。

缺陷:会产生大量的临时对象,导致频繁GC。

具体使用

使用反射首先需要知道我们操作的对象是什么,所以我们需要得到一个class对象。

获得class对象后,可以通过class对象获取class对象的方法和对象属性。进行你想要的操作,如获取方法和值,运行方法或者改变值等。

获得class对象后,拿到class对象后,可以通过class对象的构造方法,获得对象实例。

class对象的3种获取方法。

①通过全类名获取。Class c1=Class.forName("com.package.classname")

②通过对象获取  Class c2= test.getClass();    Test test;

③通过类型获取 Class c3=Test.class; 

拓展:isInstance(Object) 判断是否为某个对象实例。  isAssignableFrom(Object)判断是否为某个类的类型。

①在运行时,提供构造方法,能够使你实例化对象。

主要通过newInstance()来实现对象的实例化。

无参的构造函数,获取实例化对象。

(1)当Class对象拥有一个无参的构造函数时。我们可以直接通过Class 对象的newInstance来实现对象的实例化。

    Test test=(Test)c3.newInstance();

获取指定参数的构造函数,获取实例化对象。

(2)当我们需要初始化一个有参的对象时。我们可以获取该Class对象指定的构造函数,我们需要获取共有的构造函数。

    Constructor constructor=c3.getConstructor(String.class);//获取形参为String 类型的构造函数 的构造器

    Test t3=(Test)constructor.newInstance("1123");//通过Constructor  对象的newInstance 方法实例化对象

    t3.showLog();//测试实例化对象的使用 调用方法。

Array类

(3)数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference 其中的Array类为

         java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象。

         Object array= Array.newInstance(int.class,10);//创建一个长度为10的int数组

          Array.set(array,5,1);//设置指定位置值

          Log.e("value",String.valueOf(Array.get(array,5)));//获取指定位置值

构造函数获取,方法介绍:

公有构造方法

Constructor getConstructor(Class[] params) -- 获得指定带参共公共(自己和父类的public)构造函数

Constructor[] getConstructors() -- 获得类的所有公共(自己和父类的public)构造函数

私有构造方法

Constructor getDeclaredConstructor(Class[] params) --获得指定带参构造函数 (包含自己私有的,不包含父类)

Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数  (包含自己私有的,不包含父类)

拓展:

public native boolean isInstance(Object obj);//判断是否为某个类的实例

public boolean isAssignableFrom(Class cls);//判断是否为某个类的类型

②在运行时,提供调用对象方法的方法。能够让你操作对象的方法。

(1)Method method=c3.getMethod("showLog");//公有  无参

     method.invoke(t3);

(2)Method method=c3.getMethod("showLog",String.class);//公有 带参

     method.invoke(t3,"执行showLog");

(3)Method method=c3.getDeclaredMethod("showLog",String.class);//私有 带参

    method.setAccessible(true);//允许操作访问私有域

    method.invoke(t3,"执行showLog");

对象内方法获取,方法介绍:

公有方法获取

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共(自己和父类的public)构造函数方法   

Method[] getMethods() -- 获得类的所有公共(自己和父类的public)构造函数方法

私有方法获取

Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法(包含自己私有的,不包含父类)

Method[] getDeclaredMethods() -- 获得类声明的所有方法(包含自己私有的,不包含父类)

③在运行时,提供获取和修改对象属性的方法。能够让你操作对象的属性。

公有对象属性

(1)   Field field=c3.getField("pbName");//获取指定名字 共有Class对象属性

       Log.e("filedPb", field.getName());//获取对象属性 名称

       Log.e("filedPb", (String) field.get(t3));//获取对象该指定属性值

私有对象属性

(2)Field field1=c3.getDeclaredField("prName");//获取指定名字 私有对象属性

         Log.e("filedPr", field.getName());

         Log.e("filedPr", (String) field.get(t3));//打印改变前属性值

         field1.setAccessible(true);//设置作用域 可操作性私有

         field1.set(t3,"33333");//更改对象变量属性 

         Log.e("filedPr", (String) field1.get(t3)); //打印改变后属性值

对象属性获取,方法介绍:

公有对象属性

Field getField(String name) -- 获得命名的公共自己和父类的public)字段

Field[] getFields() -- 获得类的所有公共自己和父类的public)字段

私有对象属性

Field getDeclaredField(String name) -- 获得类声明的命名的字段(包含自己私有的,不包含父类)

Field[] getDeclaredFields() -- 获得类声明的所有字段(包含自己私有的,不包含父类)

反射和泛型结合使用场景。获取泛型类的类型。(以后补充)

Type直接子接口(Gson泛型解析会使用)

TypeVariable  泛型类型变量。可以泛型上下限等信息;

ParameterizedType  具体的泛型类型,可以获得元数据中泛型签名类型(泛型真实类型)

ParameterizedType genType = (ParameterizedType) getClass().getGenericSuperclass();

GenericArrayType  当需要描述的类型是泛型类的数组时,比如List[],Map[],此接口会作为Type的实现。

WildcardType 通配符泛型,获得上下限信息;

上一篇下一篇

猜你喜欢

热点阅读