[Android][Reflection] Reflection mechanism

Introduction to Class

The Class class is very special. It has no common construction method. It is called by jvm (simple understanding: new object or when loaded by the class loader). In Java, each class has a corresponding Class object. In other words, when we write a class, after the compilation is complete, a Class object will be generated in the generated .class file to represent the type information of this class.

All types in Java, including basic types such as int and float, have Class objects related to them. If you know the corresponding Class name, you can Class.forName()be constructed corresponding Class object, if no corresponding class, or not loaded in, then throws ClassNotFoundException object.

Class acquisition method

  • Use the object to call the getClass() method to obtain the Class instance of the object;
  • Use the static method forName() of the Class class to obtain a Class instance by the name of the class;
  • Use the method of .class to obtain the Class instance. For the package class of the basic data type, you can also use .TYPE to obtain the Class instance of the corresponding basic data type;

You can look at the code example below:

    //方式一
    Person person = new Person();
    Class<? extends Person> personClazz01 = person.getClass();
 
    //方式二
    try {
        Class<?> personClazz02 = Class.forName("Person");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
 
    //方式三
    Class<? extends Person> personClazz03 = Person.class;

Friendly reminder: During operation, if we want to generate an object of a certain class, the Java Virtual Machine (JVM) will check whether the Class object of this type has been loaded. If it is not loaded, the JVM will find the .class file based on the name of the class and load it. Once a Class object of a certain type has been loaded into memory, it can be used to generate all objects of that type.

Important methods in Class

  • public Annotation[] getAnnotations () Get all annotations in this class

  • getClassLoader() Get the class loader that loaded this class

  • getDeclaredMethods() Get all the methods in this class

  • getReturnType() Get the return type of the method

  • getParameterTypes() Get the incoming parameter types of the method

  • isAnnotation() Test whether this class is an annotation class

  • getDeclaredConstructors() Get all the constructors

  • getDeclaredMethod(String name, Class… parameterTypes) Get the specified construction method (parameter: parameter type.class)

  • getSuperclass() Get the superclass of this class

  • getInterfaces() Get all the interfaces implemented by this class

  • getFields() Get all publicly modified member variables in this class

  • getField(String name) Get the public-modified member variable of the specified name

  • newInstance() returns a new instance of the class represented by this Class, created by calling the default (that is, no-argument) constructor

Reflection use cases

Person class

public class Person {
private int age;
private String name;
public Person(){
 
}
public Person(int age, String name){
    this.age = age;
    this.name = name;
}
public int getAge() {
    return age;
}
public void setAge(int age) {
    this.age = age;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
}  

SuperPerson class

public class SuperPerson extends Person implements Smoke.Smoking{
private boolean isMan;
public void fly()
{
    System.out.println("走你~~");
}
public boolean isMan() {
    return isMan;
}
public void setMan(boolean iaMan) {
    isMan = iaMan;
}
@Override
public void smoke(int count) {
 
}
}

Smoke interface class

public class Smoke {
public interface Smoking {
    public void smoke(int count);
}
} 

MainActivity class

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Tests();
}
private void Tests() {
    try {
        //通过Java反射机制得到类的包名和类名
        Test1();
        System.out.println("===============================================");
        //验证所有的类都是Class类的实例对象
        Test2();
        System.out.println("===============================================");
        //通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在],无参构造
        Test3();
        System.out.println("===============================================");
        //通过Java反射机制得到一个类的构造函数,并实现构造带参实例对象
        Test4();
        System.out.println("===============================================");
        //通过Java反射机制操作成员变量, set 和 get
        Test5();
        System.out.println("===============================================");
        //通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等
        Test6();
        System.out.println("===============================================");
        //通过Java反射机制调用类中方法
        Test7();
        System.out.println("===============================================");
        //通过Java反射机制获得类加载器
        Test8();
        System.out.println("===============================================");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Test1() method

/**
* Demo1: 通过Java反射机制得到类的包名和类名
*/
public static void Test1() {
    Person person = new Person();
    System.out.println("Test1: 包名: " + person.getClass().getPackage().getName() + "," + "完整类名: " + person.getClass().getName());
}

Test2() method

/**
* Demo2: 验证所有的类都是Class类的实例对象
*/
public static void Test2() throws ClassNotFoundException {
    //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类
    Class<?> class1 = null;
    Class<?> class2 = null;
 
    //写法1, 可能抛出 ClassNotFoundException [多用这个写法]
    class1 = Class.forName("com.tuba.yuanyc.audiomanagerdemo.Person");
    System.out.println("Test2:(写法1) 包名: " + class1.getPackage().getName() + "," + "完整类名: " + class1.getName());
 
    //写法2
    class2 = Person.class;
    System.out.println("Test2:(写法2) 包名: " + class2.getPackage().getName() + "," + "完整类名: " + class2.getName());
}

Test3() method

/**
* Demo3: 通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在]
*/
public static void Test3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    Class<?> class1 = null;
    class1 = Class.forName("com.android.reflect.Person");
    //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
    Person person = (Person) class1.newInstance();
    person.setAge(26);
    person.setName("kaiven");
    System.out.println("Test3: " + person.getName() + " : " + person.getAge());
}

Test4() method

/**
* Demo4: 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
*/
public static void Test4() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Class<?> class1 = null;
    Person person1 = null;
    Person person2 = null;
    class1 = Class.forName("com.android.reflect.Person");
    //得到一系列构造函数集合
    Constructor<?>[] constructors = class1.getConstructors();
    try {
        person1 = (Person) constructors[0].newInstance();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    person1.setAge(28);
    person1.setName("zhuk");
    person2 = (Person) constructors[1].newInstance(29, "zhuk");
    System.out.println("Test4: " + person1.getName() + " : " + person1.getAge() + "  ,   " + person2.getName() + " : " + person2.getAge());
}

Test5() method

/**
* Demo5: 通过Java反射机制操作成员变量, set 和 get
*/
public static void Test5() throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException, InstantiationException, ClassNotFoundException {
    Class<?> class1 = null;
    class1 = Class.forName("com.android.reflect.Person");
    Object obj = class1.newInstance();
    Field nameField = class1.getDeclaredField("name");
    nameField.setAccessible(true);
    nameField.set(obj, "cyy");
    System.out.println("Test5: 修改属性之后得到属性变量的值:" + nameField.get(obj));
}

Test6() method

/**
* Demo6: 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等
*/
public static void Test6() throws ClassNotFoundException {
    Class<?> class1 = null;
    class1 = Class.forName("com.android.reflect.Person");
    //取得父类名称
    Class<?> superClass = class1.getSuperclass();
    System.out.println("Test6:  SuperMan类的父类名: " + superClass.getName());
    System.out.println("===============================================");
    Field[] fields = class1.getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
        System.out.println("类中的成员: " + fields[i]);
    }
    System.out.println("===============================================");
    //取得类方法
    Method[] methods = class1.getDeclaredMethods();
    for (int i = 0; i < methods.length; i++) {
        System.out.println("Test6,取得SuperMan类的方法:");
        System.out.println("函数名:" + methods[i].getName());
        System.out.println("函数返回类型:" + methods[i].getReturnType());
        System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
        System.out.println("函数代码写法: " + methods[i]);
    }
    System.out.println("===============================================");
    Class<?> interfaces[] = class1.getInterfaces();
    for (int i = 0; i < interfaces.length; i++) {
        System.out.println("实现的接口类名: " + interfaces[i].getName());
    }
}

Test7() method

/**
* Demo7: 通过Java反射机制调用类方法
*/
public static void Test7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {
    Class<?> class1 = null;
    class1 = Class.forName("com.android.reflect.SuperPerson");
 
    System.out.println("Test7: \n调用无参方法fly():");
    Method method = class1.getMethod("fly");
    method.invoke(class1.newInstance());
 
    System.out.println("调用有参方法smoke(int m):");
    method = class1.getMethod("smoke", int.class);
    method.invoke(class1.newInstance(), 100);
}

Test8() method

/**
* Demo8: 通过Java反射机制得到类加载器信息
* @throws ClassNotFoundException
*/
public static void Test8() throws ClassNotFoundException {
    Class<?> class1 = null;
    class1 = Class.forName("com.android.reflect.SuperPerson");
    String name = class1.getClassLoader().getClass().getName();
    System.out.println("Test8: 类加载器类名: " + name);
}
} 

operation result

01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test1: 包名: com.tuba.yuanyc.audiomanagerdemo,完整类名: com.tuba.yuanyc.audiomanagerdemo.Person
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test2:(写法1) 包名: com.android.reflect,完整类名: com.tuba.yuanyc.audiomanagerdemo.Person
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test2:(写法2) 包名: com.android.reflect,完整类名: com.tuba.yuanyc.audiomanagerdemo.Person
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test3: zhuk : 26
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test4: yyc : 28  ,   yyc : 29
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test5: 修改属性之后得到属性变量的值:cyy
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test6:  SuperMan类的父类名: java.lang.Object
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 类中的成员: private java.lang.String com.tuba.yuanyc.audiomanagerdemo.Person.name
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 类中的成员: private int com.android.reflect.Person.age
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test6,取得SuperMan类的方法:
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数名:getAge
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数返回类型:int
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数访问修饰符:public
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数代码写法: public int com.tuba.yuanyc.audiomanagerdemo.Person.getAge()
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test6,取得SuperMan类的方法:
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数名:getName
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数返回类型:class java.lang.String
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数访问修饰符:public
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数代码写法: public java.lang.String com.tuba.yuanyc.audiomanagerdemo.Person.getName()
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test6,取得SuperMan类的方法:
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数名:setAge
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数返回类型:void
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数访问修饰符:public
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数代码写法: public void com.tuba.yuanyc.audiomanagerdemo.Person.setAge(int)
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test6,取得SuperMan类的方法:
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数名:setName
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数返回类型:void
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数访问修饰符:public
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 函数代码写法: public void com.tuba.yuanyc.audiomanagerdemo.Person.setName(java.lang.String)
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test7:
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 调用无参方法fly():
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 走你~~
01-28 17:19:29.463  14972-14972/? I/System.out﹕ 调用有参方法smoke(int m):
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================
01-28 17:19:29.463  14972-14972/? I/System.out﹕ Test8: 类加载器类名: dalvik.system.PathClassLoader
01-28 17:19:29.463  14972-14972/? I/System.out﹕ ===============================================  

Reflect to modify private variables

try {
  Student student = new Student("Han MeiMei");
  System.out.println("origin grade is " + student.getGrade());
 
  Class studentClass = Student.class;
  // 获取声明的 grade 字段,这里要注意 getField 和 getDeclaredField 的区别
  Field gradeField = studentClass.getDeclaredField("grade");
  
  // 如果是 private 或者 package 权限的,一定要赋予其访问权限
  gradeField.setAccessible(true);
  
  // 修改 student 对象中的 Grade 字段值
  gradeField.set(student, 2);
  System.out.println("after reflection grade is " + student.getGrade());
 
} catch (ReflectiveOperationException e) {
  e.printStackTrace();
}

Reflective call private method

try {
  Student student = new Student("Han MeiMei");
  
  // 获取私有方法,同样注意 getMethod 和 getDeclaredMethod 的区别
  Method goMethod = Student.class.getDeclaredMethod("goToSchool", null);
  // 赋予访问权限
  goMethod.setAccessible(true);
 
  // 调用 goToSchool 方法。
  goMethod.invoke(student, null);
 
} catch (ReflectiveOperationException e) {
  e.printStackTrace();
}

The above test methods basically cover the usual reflection methods.

Summary of reflection usage

When implementing related functions through reflection, the first thing is to read the source code carefully, clarify the context, and then find the breakthrough points. These points are generally static methods or singleton objects, and finally the code implementation.

Guess you like

Origin blog.csdn.net/xfb1989/article/details/110875481