Android reflection

First we have a test class as follows - TestClassCtor:

package com.chinatsp.javalib;
 
public class TestClassCtor {
    private String name;


    private static String address = "abc";

    public TestClassCtor() {
        name = "baobao";
    }

    public TestClassCtor(int a) {

    }

    public TestClassCtor(int a, String b) {
        name = b;
    }

    private TestClassCtor(int a, double c) {

    }

    private String doSOmething(String d) {
        Log.v("baobao", "TestClassCtor, doSOmething : " + d);

        return "abcd";
    }

    private static void work() {
        Log.v("baobao", "TestClassCtor, work");
    }

    public String getName() {
        return name;
    }

    public static void printAddress() {
        Log.v("baobao", address);
    }
}

Next, we use reflection to obtain its constructor, as well as public/private functions, properties, etc.

Get an object of a class based on a string

getClass

Get the type of a class object. The type is represented by Class:

String str = "abc";
Class c1 = str.getClass();
System.out.print(c1.getName());             // java.lang.String
Class.forName

This is the method we often use to get the type. We get the type of the class through a string consisting of the namespace of the class and the name of the class.

Class c1 = Class.forName("com.chinatsp.javalib.TestClassCtor");
System.out.print(c1.getName());             // com.chinatsp.javalib.TestClassCtor

Get all public or private, static or instance fields, methods and properties in a class

Get the constructor of the class

Including public/private, including no parameters/with parameters

Class c1 = Class.forName("com.chinatsp.javalib.TestClassCtor");
// 获取类的所有的构造函数
Constructor[] constructors = c1.getDeclaredConstructors();
......

// 获取类的所有的公共的public修饰的构造函数
Constructor[] constructors = c1.getConstructors();

// 获取类的某个有参的构造函数,这里以两个参数的构造器为例
Class[] p2 = {String.class,int.class};
Constructor c2 = c1.getDeclaredConstructor(p2);
......


// 获取类的无参的构造函数
Constructor c1 = c1.getDeclaredConstructor();
......
Get the modified fields and parameters of the constructor of the class
Class c1 = Class.forName("com.chinatsp.javalib.TestClassCtor");
Class[] p2 = {String.class,int.class};
Constructor c2 = c1.getDeclaredConstructor(p2);
int mod = c2.getModifiers();   //输出修饰域 public
String constructorName = c2.getName();    // 输出方法名 com.chinatsp.javalib.TestClassCtor
Class[] parameterTypes = c2.getParameterTypes();  // 获取指定构造方法参数的集合
for(int j=0;j< parameterTypes.length;j++){
       // 输出打印参数列表
      System.out.print(parameterTypes[j].getName());     //   java.lang.String, int
       if(parameterTypes.length > j + 1) {
            System.out.print(", ");
       }
}
Get an instance of a class through newInstance()
  1. Get class instance through constructor
// 获取有两个参数的构造函数
 Class c = Class.forName("com.chinatsp.javalib.TestClassCtor");
 Class[] p = {String.class,int.class};
Constructor ctor = c.getDeclaredConstructor(p3);
// 获取类实例,为两个参数的构造函数赋值
Object obj = ctor.newInstance("bjq",1);
 if(obj instanceof TestClassCtor){
       System.out.println("obj is TestClassCtor");
       TestClassCtor testClassCtor = (TestClassCtor) obj;
       System.out.println("testClassCtor.a = " + testClassCtor.getA() + ",name=" + testClassCtor.getName());
}
================================================================================
obj is TestClassCtor
testClassCtor.a = 1,name=bjq
==============================================================================


// 获取无参的构造函数
Constructor ctor1 = c.getDeclaredConstructor();
Object obj1 = ctro1.newInstance();
 if(obj1 instanceof TestClassCtor){
       System.out.println("obj1 is TestClassCtor");
       TestClassCtor testClassCtor1 = (TestClassCtor) obj1;
       System.out.println("testClassCtor1.a = " + testClassCtor1.getA() + ",name=" + testClassCtor1.getName());
}
================================================================================
obj1 is TestClassCtor
testClassCtor1.a = 0,name=baobao
==============================================================================

  1. Use Class.newInstance()

If the constructor is parameterless, you can directly use the newInstance method of Class to create a class instance.

Class c = Class.forName("com.chinatsp.javalib.TestClassCtor");
Object obj2 = c.newInstance();
 if(obj2 instanceof TestClassCtor){
       System.out.println("obj2 is TestClassCtor");
       TestClassCtor testClassCtor2 = (TestClassCtor) obj2;
       System.out.println("testClassCtor2.a = " + testClassCtor2.getA() + ",name=" + testClassCtor2.getName());
}
================================================================================
obj2 is TestClassCtor
testClassCtor2.a = 0,name=baobao
==============================================================================
Get the private method of the class and call it

In TestClassCtor, there is a private method doSomething. If you want to get this private method and execute it, you can do as follows:

// 获取类实例
 Class c = Class.forName("com.chinatsp.javalib.TestClassCtor");
Object obj = c.newInstance();
// 以下五行代码获取private方法并调用该private方法
 Class[] p = {String.class}; // doSomething()需要一个字符串参数
 Method method = c.getDeclaredMethod("doSomething", p); // 在指定类中获取指定方法
method.setAccessible(true);
Object argList[] = {"jianqiang"};
Object result = method.invoke(objCtor,argList);

System.out.println(result);


================================================================================
TestClassCtro,doSomething : jianqiang
abcd
================================================================================
Get the static private method of the class and call it

In TestClassCtro, there is a static private method work:

Class r2 = Class.forName("com.chinatsp.javalib.TestClassCtor");
Method method2 = r2.getDeclaredMethod("work");
method2.setAccessible(true);
method2.invoke(null);

================================================================================
TestClassCtor, work
================================================================================

Get the private instance field of a class and modify it

In TestClassCtro, there is a private instance field name

// 获取类实例
Class c = Class.forName("com.chinatsp.javalib.TestClassCtor");
Class[] p = {int.class, String.class};
Constructor ctor = c.getDeclaredConstructor(p);
Object obj = ctor.newInstance(1, "bjq");

// 获取name字段
Field field = c.getDeclaredField("name");
field.setAccessible(true);
// 获取了obj对象,此时是TestClassCtor对象中的name字段
// 方法:get(Object obj) 返回指定对象obj上此 Field 表示的字段的值,此处不能是null
Object fieldObject = field.get(obj);
if(fieldObject instanceof String){
      String name = (String) fieldObject;
      System.out.println(name);                //  bjq
}

// 修改name字段的值,注意是obj实例中的name
// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
field.set(obj, "jianqiang1982");
Object fieldObject1 = field.get(obj);
if(fieldObject1 instanceof String){
      String name = (String) fieldObject1;
      System.out.println(name);             //  jianqiang1982
}
Get the private static field of a class and modify it

In TestClassCtro, there is a static private field address, and I want to get it and modify its value.

Class r = Class.forName("com.chinatsp.javalib.TestClassCtor");
Field field = r.getDeclaredField("address");
field.setAccessible(true);
// 传入任何对象都可以
Object fieldObject = field.get(null);
field.set(fieldObject,"ABCD");
TestClassCtro.printAddress();      // ABCD

Notice

There is a slight difference in how we get private static fields and private non-static fields.
If the field is a non-static field, the object parameter passed in the field.get(Object obj); method must be passed in the object of the reflection class. If null is passed, a java.lang.NullPointerException will be reported. If the field is a static
field, pass in Any object is acceptable, including null

Reflection on generic classes

Look at the following singleton classSingleton

package com.chinatsp.javalib;

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

SingletonIt is a generic class and an abstract class. AMN.class is its implementation:

package com.chinatsp.javalib;

public class AMN {
    private static final Singleton<ClassB2Interface> gDefault = new Singleton<ClassB2Interface>() {
        @Override
        protected ClassB2Interface create() {
            ClassB2 b2 = new ClassB2();
            b2.id = 2;
            return b2;
        }
    };

    static public ClassB2Interface getDefault(){
        return gDefault.get();
    }

    static public void fun(){

    }
}

In the above code, gDefault is a static private variable of AMN, which is of Singleton type, so the create() method must be implemented to return an object of ClassB2 type. The implementation of ClassB2 is as follows:

package com.chinatsp.javalib;

public class ClassB2 implements ClassB2Interface{
    public int id;
    @Override
    public void doSomething() {
        System.out.println("ClassB2 doSomething");
    }
}

ClassB2 implements the ClassB2Interface interface, ClassB2Interface class:

package com.chinatsp.javalib;

public interface ClassB2Interface {
   public void doSomething();
}

Singletonis a generic type, for which we can obtain the fields Singletonin through the following code mInstance;

// 获取Singleton中的mInstance字段
Class<?> singleton = Class.forName("com.chinatsp.javalib.Singleton");
Field mInstanceField = singleton.getDeclaredField("mInstance");
mInstanceField.setAccessible(true);

Class<?> activityManagerNativeClass = Class.forName("com.chinatsp.javalib.AMN");
Field gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
gDefaultField.setAccessible(true);
// 获取到gDefault字段的值,此时代表的是一个Singleton<ClassB2Interface>对象
Object gDefault = gDefaultField.get(null);

//AMN 的gDefault 对象里面原始的B2对象
// 获取gDefault中的mInstance字段的值,此时是ClassB2对象
Object rawB2Object = mInstanceField.get(gDefault);
if(rawB2Object instanceof ClassB2){
  	System.out.println("rawB2Object is ClassB2");        
}
Notice

To get the object gDefaultin ClassB2(that is, mInstanceField.get(gDefault);the value obtained), you need to execute it first AMN.getDefault().doSomething();. This line of code is to assign a value to the field gDefaultin mInstance. Call the get method that will be called, then call the method, and then return the method called . an objectAMN的getDefault()SingletonSingletoncreateAMN中gDefaultcreateClassB2

Guess you like

Origin blog.csdn.net/jxq1994/article/details/130557411