reflejo de android

Primero tenemos una clase de prueba de la siguiente manera 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);
    }
}

A continuación, utilizamos la reflexión para obtener su constructor, así como funciones públicas/privadas, propiedades, etc.

Obtener un objeto de una clase basado en una cadena

obtener clase

Obtenga el tipo de un objeto de clase. El tipo está representado por Clase:

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

Este es el método que usamos a menudo para obtener el tipo: obtenemos el tipo de la clase a través de una cadena que consta del espacio de nombres de la clase y el nombre de la clase.

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

Obtenga todos los campos, métodos y propiedades públicos o privados, estáticos o de instancia en una clase

Obtener el constructor de la clase.

Incluyendo público/privado, incluyendo sin parámetros/con parámetros

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();
......
Obtener los campos y parámetros modificados del constructor de la clase.
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(", ");
       }
}
Obtener una instancia de una clase a través de newInstance()
  1. Obtener instancia de clase a través del 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. Utilice Class.newInstance()

Si el constructor no tiene parámetros, puede usar directamente el método newInstance de Class para crear una instancia de clase.

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
==============================================================================
Obtenga el método privado de la clase y llámelo

En TestClassCtor, hay un método privado doSomething. Si desea obtener este método privado y ejecutarlo, puede hacer lo siguiente:

// 获取类实例
 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
================================================================================
Obtenga el método privado estático de la clase y llámelo

En TestClassCtro, existe un método privado estático work:

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

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

Obtener el campo de instancia privada de una clase y modificarlo

En TestClassCtro, hay un nombre de campo de instancia privada

// 获取类实例
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
}
Obtener el campo estático privado de una clase y modificarlo

En TestClassCtro, hay una dirección de campo privado estático y quiero obtenerla y modificar su valor.

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

Aviso

Existe una ligera diferencia en cómo obtenemos campos privados estáticos y campos privados no estáticos.
Si el campo es un campo no estático, el parámetro de objeto pasado en el método field.get(Object obj); debe pasarse en el objeto de la clase de reflexión. Si se pasa nulo, se informará una excepción java.lang.NullPointerException. Si el campo es estático
, pase Cualquier objeto es aceptable, incluido nulo.

Reflexión sobre las clases genéricas

Mira la siguiente clase singletonSingleton

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;
        }
    }
}

SingletonEs una clase genérica y una clase abstracta. AMN.class es su implementación:

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(){

    }
}

En el código anterior, gDefault es una variable privada estática de AMN, que es de tipo Singleton, por lo que se debe implementar el método create() para devolver un objeto de tipo ClassB2. La implementación de ClassB2 es la siguiente:

package com.chinatsp.javalib;

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

ClassB2 implementa la interfaz ClassB2Interface, clase ClassB2Interface:

package com.chinatsp.javalib;

public interface ClassB2Interface {
   public void doSomething();
}

Singletones un tipo genérico, del cual podemos obtener los campos Singletona través del siguiente código 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");        
}
Aviso

Para obtener gDefaultel objeto ClassB2(es decir, mInstanceField.get(gDefault);el valor obtenido), primero debe ejecutarlo AMN.getDefault().doSomething();. Esta línea de código es para asignar un valor al campo gDefaulten mInstance. Llame al método get que se llamará, luego llame al método y luego devuelve el método llamado objetoAMN的getDefault()SingletonSingletoncreateAMN中gDefaultcreateClassB2

Supongo que te gusta

Origin blog.csdn.net/jxq1994/article/details/130557411
Recomendado
Clasificación