反射

作者: lisx_ | 来源:发表于2020-04-09 15:58 被阅读0次

通过 Class 对象分别获取Constructor类对象、Method类对象 & Field 类对象

// 即以下方法都属于`Class` 类的方法。

<-- 1. 获取类的构造函数(传入构造函数的参数类型)->>
  // a. 获取指定的构造函数 (公共 / 继承)
  Constructor<T> getConstructor(Class<?>... parameterTypes)
  // b. 获取所有的构造函数(公共 / 继承) 
  Constructor<?>[] getConstructors(); 
  // c. 获取指定的构造函数 ( 不包括继承)
  Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
  // d. 获取所有的构造函数( 不包括继承)
  Constructor<?>[] getDeclaredConstructors(); 
// 最终都是获得一个Constructor类对象

// 特别注意:
  // 1. 不带 "Declared"的方法支持取出包括继承、公有(Public) & 不包括有(Private)的构造函数
  // 2. 带 "Declared"的方法是支持取出包括公共(Public)、保护(Protected)、默认(包)访问和私有(Private)的构造方法,但不包括继承的构造函数
  // 下面同理

<--  2. 获取类的属性(传入属性名) -->
  // a. 获取指定的属性(公共 / 继承)
   Field getField(String name) ;
  // b. 获取所有的属性(公共 / 继承)
   Field[] getFields() ;
  // c. 获取指定的所有属性 (不包括继承)
   Field getDeclaredField(String name) ;
  // d. 获取所有的所有属性 (不包括继承)
   Field[] getDeclaredFields() ;
// 最终都是获得一个Field类对象

<-- 3. 获取类的方法(传入方法名 & 参数类型)-->
  // a. 获取指定的方法(公共 / 继承)
    Method getMethod(String name, Class<?>... parameterTypes) ;
  // b. 获取所有的方法(公共 / 继承)
   Method[] getMethods() ;
  // c. 获取指定的方法 ( 不包括继承)
   Method getDeclaredMethod(String name, Class<?>... parameterTypes) ;
  // d. 获取所有的方法( 不包括继承)
   Method[] getDeclaredMethods() ;
// 最终都是获得一个Method类对象

<-- 4. Class类的其他常用方法 -->
getSuperclass(); 
// 返回父类

String getName(); 
// 作用:返回完整的类名(含包名,如java.lang.String ) 
 
Object newInstance(); 
// 作用:快速地创建一个类的实例
// 具体过程:调用默认构造器(若该类无默认构造器,则抛出异常 
// 注:若需要为构造器提供参数需使用java.lang.reflect.Constructor中的newInstance()

通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、方法 & 属性的具体信息 & 进行操作

// 即以下方法都分别属于`Constructor`类、`Method`类 & `Field`类的方法。

<-- 1. 通过Constructor 类对象获取类构造函数信息 -->
  String getName();// 获取构造器名
  Class getDeclaringClass();// 获取一个用于描述类中定义的构造器的Class对象
  int getModifiers();// 返回整型数值,用不同的位开关描述访问修饰符的使用状况
  Class[] getExceptionTypes();// 获取描述方法抛出的异常类型的Class对象数组
  Class[] getParameterTypes();// 获取一个用于描述参数类型的Class对象数组

<-- 2. 通过Field类对象获取类属性信息 -->
  String getName();// 返回属性的名称
  Class getDeclaringClass(); // 获取属性类型的Class类型对象
  Class getType();// 获取属性类型的Class类型对象
  int getModifiers(); // 返回整型数值,用不同的位开关描述访问修饰符的使用状况
  Object get(Object obj) ;// 返回指定对象上 此属性的值
  void set(Object obj, Object value) // 设置 指定对象上此属性的值为value
 
<-- 3. 通过Method 类对象获取类方法信息 -->
  String getName();// 获取方法名
  Class getDeclaringClass();// 获取方法的Class对象 
  int getModifiers();// 返回整型数值,用不同的位开关描述访问修饰符的使用状况
  Class[] getExceptionTypes();// 获取用于描述方法抛出的异常类型的Class对象数组
  Class[] getParameterTypes();// 获取一个用于描述参数类型的Class对象数组

<--额外:java.lang.reflect.Modifier类 -->
// 作用:获取访问修饰符

static String toString(int modifiers)   
// 获取对应modifiers位设置的修饰符的字符串表示

static boolean isXXX(int modifiers) 
// 检测方法名中对应的修饰符在modifiers中的值
package com.example.myapplication;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Ltest {

    public static abstract class Product {
        public abstract void show();
    }

    public static class ProductA extends Product {

        @Override
        public void show() {
            System.out.println("生产出了产品A");
        }
    }

    class ProductB extends Product {

        @Override
        public void show() {
            System.out.println("生产出了产品B");
        }
    }

    public static void main(String[] args) {

        //test();
        //test1();
        test2();
    }


    /**
     * 测试反射_内部类
     */
    private static void test2() {
        // 静态内部类可直接 class.newInstance
        try {
            // 1. 根据 传入的产品类名 获取 产品类类型的Class对象
            Class product_Class = Class.forName(
                    "com.example.myapplication.Ltest$ProductA");
            // 2. 通过Class对象动态创建该产品类的实例
            Product concreteProduct = (Product) product_Class.newInstance();
            concreteProduct .show();

        } catch (Exception e) {
            e.printStackTrace();
        }


        // 成员内部类需要先构造外部类
        try {
            Class outClass = Class.forName(
                    "com.example.myapplication.Ltest");

            Class innerClass = Class.forName(
                    "com.example.myapplication.Ltest$ProductB");
            // 获取非静态内部类的实例,需要先获取外部类实例
            Product b = (Product) innerClass.getDeclaredConstructors()[0].newInstance(
                    outClass.newInstance());
            b.show();
            // 另一种方式_创建实例
            Product b2 = (Product) innerClass.getDeclaredConstructor(outClass).newInstance(
                    outClass.newInstance());
            b2.show();
            // 另一种方式_调用方法
            Method method = innerClass.getDeclaredMethod("show");
            method.invoke(b);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 测试反射_基本用法
     */
    private static void test1() {

        class Student {

            private String name;

            // 无参构造函数
            public Student() {
                System.out.println("调用了无参构造函数");
            }

            // 有参构造函数
            public Student(String str) {
                System.out.println("调用了有参构造函数");
            }

            // 无参数方法
            public void setName1() {
                System.out.println("调用了无参方法:setName1()");
            }

            // 有参数方法
            public void setName2(String str) {
                System.out.println("调用了有参方法setName2 str:" + str);
            }
        }

        try {

            // 1. 获取Student类的Class对象
            Class studentClass = Student.class;

            // 3. 通过Class对象获取Student类的name属性
            Field f = studentClass.getDeclaredField("name");
            // 4. 设置私有访问权限
            f.setAccessible(true);
            // 2. 通过Class对象创建Student类的对象
            Object mStudent = studentClass.newInstance();
            // 5. 对新创建的Student对象设置name值
            f.set(mStudent, "Carson_Ho");
            // 6. 获取新创建Student对象的的name属性 & 输出
            System.out.println(f.get(mStudent));

            //利用反射调用构造函数

            // 2.1 通过Class对象获取Constructor类对象,从而调用无参构造方法
            // 注:构造函数的调用实际上是在newInstance(),而不是在getConstructor()中调用
            Object mObj1 = studentClass.getConstructor().newInstance();
            // 2.2 通过Class对象获取Constructor类对象(传入参数类型),从而调用有参构造方法
            Object mObj2 = studentClass.getConstructor(String.class).newInstance("Carson");


            // 3.1 通过Class对象获取方法setName1()的Method对象:需传入方法名
            // 因为该方法 = 无参,所以不需要传入参数
            Method msetName1 = studentClass.getMethod("setName1");
            // 通过Method对象调用setName1():需传入创建的实例
            msetName1.invoke(mStudent);
            // 3.2 通过Class对象获取方法setName2()的Method对象:需传入方法名 & 参数类型
            Method msetName2 = studentClass.getMethod("setName2", String.class);
            // 通过Method对象调用setName2():需传入创建的实例 & 参数值
            msetName2.invoke(mStudent, "Carson_Ho");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 测试class_name
     */
    private static void test() {
        // 对于2个String类型对象,它们的Class对象相同
        Class<?> c1, c2, c3, c4;
        c1 = "Carson".getClass();
        c2 = null;
        try {
            c2 = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        c3 = String.class;
        c4 = Boolean.TYPE;
        System.out.println("1=" + c1);
        System.out.println("2=" + c2);
        System.out.println("3=" + c3);
        System.out.println("4=" + c4);
    }
}

相关文章

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • 镜面反射矩阵的推导

    镜面反射是以镜面作为反射平面,实物与反射物到反射平面的距离相等,实物与反射物方向相反,所以,反射矩阵由反射平面确定...

  • reflect.go包学习_之二 指针操作提高反射性能 反射应用

    reflect.go包学习_之二 指针操作提高反射性能 反射应用 反射创建实例 反射信息、反射调用方法、反射修改值...

  • Java互联网公司-经典面试题附答案

    基础:Java 反射?反射有什么缺点?你是怎么理解反射的(为什么框架需要反射)?优点:反射具有解耦性,缺点:反射属...

  • Java反射与joor反射库的使用

    java原生反射的使用 反射构造对象 反射方法 反射字段 joor反射库的使用 github:https://gi...

  • Java反射

    什么是反射? 反射的作用? 反射性能优化?

  • 反射三定律

    反射第一定律:反射可以将interface类型变量转换成反射对象 反射第二定律:反射可以将反射对象还原成inter...

  • 反射

    1.反射是什么?反射的定义,概念 2.为什么要学反射? 3.怎么使用反射?反射的使用

  • 一周岁前做好两件事,孩子就不会语言迟缓,保证口齿伶俐

    与语言发展相关的原始反射有四个:张口反射、足跖反射、抓握反射和手拉反射,每个反射的发生、发展和整合都是次第进行的,...

  • 面试官问go反射第一弹

    目录 反射概念 reflect包 反射类型(Type)和种类(Kind) 反射类型(Type)使用 反射类型对象(...

网友评论

      本文标题:反射

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