2022-07-29

反射的基本使用方法

Java反射用的很多,像Retrofit、Dagger、Hook、插件化等等很多地方都有用到,掌握Java反射的使用十分必要,了解反射原理就更好了。这里就简单的介绍下反射的基本用法。

先把Student.class贴一下

@ClassAnnotation(value = 20)
public class Student {
    @FieldAnnotation
    public static int staticFiled;
    public static final int FINAL_FILED = 100;
    private String name;
    public int age;

    @ConstructorAnnotation(value = 40)
    public Student() {
    }

    private Student(int age) {
        this.age = age;
        System.out.println("Constructor age!");
    }

    private Student(String name) {
        this.name = name;
        System.out.println("Constructor name!");
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Constructor name & age!");
    }

    public String getName() {
        return name;
    }

    @MethodAnnotation
    public void setName(String name) {
        this.name = name;
        System.out.println("invoke public Method!");
    }

    private int getAge() {
        return age;
    }

    private void setAge(int age) {
        this.age = age;
        System.out.println("invoke private Method!");
    }

    public static void staticMethod() {
        System.out.println("invoke static Method!");
    }
}
三种反射方法
//方式一
try {
    Class<?> clazz1 = Class.forName("com.example.myapplication.reflection.Student");
    System.out.println("Class.forName: " + clazz1.getName());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

//方式二
Class<Student> clazz2 = Student.class;
System.out.println("Student.class: " + clazz2.getName());

//方式三
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
System.out.println("student.getClass(): " + clazz3.getName());
获取构造器
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
System.out.println("student.getClass(): " + clazz3.getName());

//获取所有的构造器
Constructor<?>[] constructors = clazz3.getDeclaredConstructors();
System.out.print("get all Constructors");
for (Constructor<?> constructor : constructors) {
    Class<?>[] parameterTypes = constructor.getParameterTypes();
    System.out.print("parameters length: " + parameterTypes.length);
    System.out.print(" constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
    System.out.print("\n");
}

//获取public的构造器
constructors = clazz3.getConstructors();
System.out.print("get public Constructors");
for (Constructor<?> constructor : constructors) {
    Class<?>[] parameterTypes = constructor.getParameterTypes();
    System.out.print("parameters length: " + parameterTypes.length);
    System.out.print(" constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
    System.out.print("\n");
}

//获取指定参数的构造器
Class<?>[] parameters = {int.class};
Constructor<?> constructor;
try {
    System.out.print("get public Constructors");
    constructor = clazz3.getDeclaredConstructor(parameters);
    System.out.println("constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    constructor.setAccessible(true);
    constructor.newInstance(11);
} catch (Exception e) {
    e.printStackTrace();
}

执行结果:

get all Constructors
parameters length: 2 constructor Modifier: public java.lang.String int
parameters length: 1 constructor Modifier: private java.lang.String
parameters length: 1 constructor Modifier: private int
parameters length: 0 constructor Modifier: public

get public Constructors
parameters length: 2 constructor Modifier: public java.lang.String int
parameters length: 0 constructor Modifier: public

get public Constructors
constructor Modifier: private
Constructor age!

反射字段
Student student = new Student("大白", 1);
Class<? extends Student> clazz3 = student.getClass();

Field[] fields = clazz3.getDeclaredFields();
System.out.print("fields length: " + fields.length);
for (Field field : fields) {
    System.out.print("field Modifier: " + Modifier.toString(field.getModifiers()));
    System.out.print(" " + field.getName());
}

fields = clazz3.getFields();
System.out.print("fields length: " + fields.length);
for (Field field : fields) {
    System.out.print("field Modifier: " + Modifier.toString(field.getModifiers()));
    System.out.print(" " + field.getName());
}

try {
    Field field = clazz3.getDeclaredField("FINAL_FILED");
    System.out.println("fields FINAL_FILED value: " + field.get(null));

    field = clazz3.getDeclaredField("name");
    field.setAccessible(true);
    System.out.println("fields name value: " + field.get(student));
    field.set(student, "小白");
    System.out.println("fields name value: " + field.get(student));
} catch (Exception e) {
    e.printStackTrace();
}

执行结果:
fields length: 4
field Modifier: public static staticFiled
field Modifier: public static final FINAL_FILED
field Modifier: private name
field Modifier: public age

fields length: 3
field Modifier: public static staticFiled
field Modifier: public static final FINAL_FILED
field Modifier: public age

fields FINAL_FILED value: 100
fields name value: 大白
fields name value: 小白
Constructor name & age!

这里使用了反射修改了name字段的值,并使用field.setAccessible(true);修改了name字段的访问权限

反射方法
Student student = new Student("大白", 1);
Class<? extends Student> clazz3 = student.getClass();

System.out.println("get all methods");
Method[] methods = clazz3.getDeclaredMethods();
System.out.println("methods length: " + methods.length);
for (Method method : methods) {
    Class<?>[] parameterTypes = method.getParameterTypes();
    System.out.print("method name: " + method.getName());
    System.out.print(" method Modifier: " + Modifier.toString(method.getModifiers()));
    System.out.print(" parameters length: " + parameterTypes.length);
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
}

methods = clazz3.getMethods();
System.out.println("methods length: " + methods.length);
for (Method method : methods) {
    Class<?>[] parameterTypes = method.getParameterTypes();
    System.out.print("method name: " + method.getName());
    System.out.print(" method Modifier: " + Modifier.toString(method.getModifiers()));
    System.out.print(" parameters length: " + parameterTypes.length);
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
}

try {
    Class<?>[] parameters = {int.class};
    Method method = clazz3.getDeclaredMethod("setAge", parameters);
    method.setAccessible(true);
    System.out.println("fields age value: " + student.age);
    method.invoke(student, 20);
    System.out.println("fields age value: " + student.age);
} catch (Exception e) {
    e.printStackTrace();
}

try {
    Method method = clazz3.getDeclaredMethod("staticMethod");
    method.setAccessible(true);
    method.invoke(null);
} catch (Exception e) {
    e.printStackTrace();
}

执行结果:

get all methods
methods length: 5

method name: getName method Modifier: public parameters length: 0
method name: setName method Modifier: public parameters length: 1 java.lang.String
method name: staticMethod method Modifier: public static parameters length: 0
method name: getAge method Modifier: private parameters length: 0
method name: setAge method Modifier: private parameters length: 1 int

methods length: 12

method name: getName method Modifier: public parameters length: 0
method name: setName method Modifier: public parameters length: 1 java.lang.String
method name: staticMethod method Modifier: public static parameters length: 0
method name: wait method Modifier: public final native parameters length: 1 long
method name: wait method Modifier: public final parameters length: 2 long int
method name: wait method Modifier: public final parameters length: 0
method name: equals method Modifier: public parameters length: 1 java.lang.Object
method name: toString method Modifier: public parameters length: 0
method name: hashCode method Modifier: public native parameters length: 0
method name: getClass method Modifier: public final native parameters length: 0
method name: notify method Modifier: public final native parameters length: 0
method name: notifyAll method Modifier: public final native parameters length: 0

fields age value: 1
invoke private Method!
fields age value: 20

invoke static Method!

这里需要注意的是clazz3.getMethods返回的长度是12,包括父类Object中的public方法

反射注解
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
Annotation[] annotations = clazz3.getDeclaredAnnotations();
System.out.println("annotations length: " + annotations.length);
for (Annotation annotation : annotations) {
    if (annotation instanceof ClassAnnotation) {
        System.out.println("annotations name: " + ((ClassAnnotation) annotation).value());
    }
    Class<? extends Annotation> clazz = annotation.annotationType();
    System.out.print("annotations Modifier: " + Modifier.toString(clazz.getModifiers()));
}

//获取指定参数的构造器
Class<?>[] parameters = {};
try {
    Constructor<?> constructor = clazz3.getDeclaredConstructor(parameters);
    annotations = constructor.getDeclaredAnnotations();
    System.out.println("annotations length: " + annotations.length);
    for (Annotation annotation : annotations) {
        if (annotation instanceof ConstructorAnnotation) {
            System.out.println("annotations name: " + ((ConstructorAnnotation) annotation).value());
        }
        Class<? extends Annotation> clazz = annotation.annotationType();
        System.out.print("annotations Modifier: " + Modifier.toString(clazz.getModifiers()));
    }
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

执行结果:

annotations length: 1
annotations name: 20
annotations Modifier: public abstract interface

annotations length: 1
annotations name: 40
annotations Modifier: public abstract interface

这里补上自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ClassAnnotation {
    int value() default 1;
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface ConstructorAnnotation {
    int value() default 1;
}

其他注解的使用和上面类似,这里就不做分享了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 什么是反射 反射是一个很牛的功能,能够在程序运行时修改程序的行为。但是反射是非常规手段,反射有风险,应用需谨慎。把...
    dashingqi阅读 637评论 0 1
  • 深入理解Java注解 依赖注入是一种较流行的设计模式,在 Android开发中也有很多实用的依赖注入框架,可以帮助...
    niuniu_it阅读 305评论 0 1
  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 2,048评论 0 3
  • 自己备忘,随便写 android网络框架源码解析及对比 android常用网络框架对比 Volley: 特点 基于...
    幻海流心阅读 1,571评论 0 4
  • 官方文档 The Apache Groovy programming language Groovy Langua...
    LeonXtp阅读 544评论 0 0