美文网首页
Java基础-反射

Java基础-反射

作者: 森屿暖茶 | 来源:发表于2021-01-27 18:34 被阅读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 通配符泛型,获得上下限信息;

    相关文章

      网友评论

          本文标题:Java基础-反射

          本文链接:https://www.haomeiwen.com/subject/wtjlgktx.html