Exciter

生命不息、折腾不止

0%

Java反射核心基础功能

反射相关的核心类:

  • Class:类
  • Method:类的方法
  • Field:类的属性/成员变量
  • Constructor:类的构造方法
  • invoke:方法调用
    1 反射的基本用法
    通过反射获取类中的构造方法、普通方法、内部类、包信息、父类等。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    package site.exciter.reflect;

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;

    /**
    * 反射的基本用法
    */
    @Deprecated
    public class ClassReflectTest {

    /**
    * 私有构造方法
    */
    private ClassReflectTest() {

    }

    /**
    * 有参数的构造方法
    *
    * @param params 参数
    */
    public ClassReflectTest(String params) {
    System.out.println("有参数的构造方法");
    }

    /**
    * 无参数的普通方法
    */
    public void info() {
    System.out.println("无参数的info方法");
    }

    /**
    * 有参数的普通方法
    *
    * @param content 参数
    */
    public void info(String content) {
    System.out.println("有参数的构造方法,content = " + content);
    }

    /**
    * 静态内部类
    */
    static class Inner {

    }

    public static void main(String[] args) {
    try {
    //获取ClassReflectTest对应的Class
    Class<ClassReflectTest> clazz = ClassReflectTest.class;

    //获取ClassReflectTest所有构造方法
    Constructor<?>[] constructors = clazz.getDeclaredConstructors();
    System.out.println("-----ClassReflectTest所有的构造方法:");
    for (Constructor<?> constructor : constructors) {
    System.out.println(constructor);
    }

    //获取ClassReflectTest所有的Public构造方法
    Constructor<?>[] publicConstructors = clazz.getConstructors();
    System.out.println("-----ClassReflectTest所有的Public构造方法:");
    for (Constructor<?> constructor : publicConstructors) {
    System.out.println(constructor);
    }

    //获取ClassReflectTest所有的Public方法
    Method[] methods = clazz.getMethods();
    System.out.println("-----ClassReflectTest所有的Public方法:");
    for (Method method : methods) {
    System.out.println(method);
    }

    //获取ClassReflectTest中的指定方法
    System.out.println("-----ClassReflectTest中带有一个字符串参数的info方法:");
    System.out.println(clazz.getMethod("info", String.class));

    //获取ClassReflectTest中所有的注解
    Annotation[] annotations = clazz.getAnnotations();
    System.out.println("-----ClassReflectTest中所有的Annotation:");
    for (Annotation annotation : annotations) {
    System.out.println(annotation);
    }

    //获取ClassReflectTest中所有的内部类
    Class<?>[] inners = clazz.getDeclaredClasses();
    System.out.println("-----ClassReflectTest中所有的内部类:");
    for (Class<?> inner : inners) {
    System.out.println(inner);
    }

    //获取内部类对应的外部类
    Class<?> innerClazz = Class.forName("site.exciter.reflect.ClassReflectTest$Inner");
    System.out.println("-----内部类Inner所在的外部类:");
    System.out.println(innerClazz.getDeclaringClass());

    System.out.println("------ClassReflectTest所在的包:" + clazz.getPackage());
    System.out.println("------ClassReflectTest的父类:" + clazz.getSuperclass());

    } catch (NoSuchMethodException | ClassNotFoundException e) {
    e.printStackTrace();
    }
    }

    }
    2 通过反射调用方法
    通过invoke()可以实现对目标对象的的方法调用。
    首先新建一个User对象,用来存储用户信息:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package site.exciter.reflect;

    public class User {
    private String name;
    private String age;

    public User() {

    }

    public User(String name) {
    this.name = name;
    }

    private void setName(String name) {
    this.name = name;
    }

    private String getName() {
    return name;
    }

    @Override
    public String toString() {
    return "User{" +
    "name='" + name + '\'' +
    ", age='" + age + '\'' +
    '}';
    }
    }
    然后再测试类中调用User对象中的方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package site.exciter.reflect;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    /**
    * 通过反射调用方法
    */
    public class MethodReflectTest {
    public static void main(String[] args) {
    User user = new User("张狗蛋");
    Class<?> clazz = user.getClass();
    try {
    Method method1 = clazz.getDeclaredMethod("setName", String.class);
    Method method2 = clazz.getDeclaredMethod("getName");
    //setName和getName为私有方法,setAccessible为true才能能正常invoke
    method1.setAccessible(true);
    method2.setAccessible(true);
    System.out.println("---before:" + method2.invoke(user));
    method1.invoke(user, "李铁柱");
    System.out.println("---after:" + method2.invoke(user));
    } catch (NoSuchMethodException
    | IllegalAccessException
    | IllegalArgumentException
    | InvocationTargetException e) {
    e.printStackTrace();
    }
    }
    }
    3 通过反射访问类的属性
    getField()getFields()是反射访问类属性的核心方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package site.exciter.reflect;

    import java.lang.reflect.Field;

    /**
    * 通过反射访问类的属性
    */
    public class FieldReflectTest {
    public static void main(String[] args) {
    try {
    User user = new User();
    //获取User对应的Class对象
    Class<User> clazz = User.class;
    //获取User中的name属性
    Field nameField = clazz.getDeclaredField("name");
    //设置通过反射访问该Field时取消访问权限检查
    nameField.setAccessible(true);
    //调用set方法给user对象名为name的Field设置值
    nameField.set(user, "赵富贵");
    Field ageField = clazz.getDeclaredField("age");
    ageField.setAccessible(true);
    ageField.set(user, "26");
    System.out.println(user.toString());
    } catch (NoSuchFieldException
    | IllegalAccessException
    | IllegalArgumentException e) {
    e.printStackTrace();
    }
    }
    }
    4 通过反射获取泛型信息
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    package site.exciter.reflect;

    import java.lang.reflect.Field;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.Map;

    /**
    * 用反射获取泛型
    */
    public class GenericReflectTest {
    private Map<String, Integer> mData;

    public static void main(String[] args) {
    try {
    Class<GenericReflectTest> clazz = GenericReflectTest.class;
    Field dataField = clazz.getDeclaredField("mData");
    Class<?> dataType = dataField.getType();
    System.out.println("mData的类型:" + dataType);
    //获取泛型类型
    Type gType = dataField.getGenericType();
    if (gType instanceof ParameterizedType) {
    ParameterizedType pType = (ParameterizedType) gType;
    //获取原始类型
    Type rType = pType.getRawType();
    System.out.println("原始类型:" + rType);
    Type[] typeArguments = pType.getActualTypeArguments();
    System.out.println("泛型类型:");
    for (int i = 0; i < typeArguments.length; i++) {
    System.out.println("第" + i + "个泛型类型是:" + typeArguments[i]);
    }
    }
    } catch (NoSuchFieldException e) {
    e.printStackTrace();
    }

    }
    }