Principle of Java reflection mechanism and simple application under Android

Do not miss passing through

Click the blue word to follow us

1. The concept of reflection and class reflection in Java

Reflection mainly refers to the ability of a program to access, detect and modify its own state or behavior. In the field of computer science, reflection is a class of applications that can describe and control themselves. This type of application uses a certain mechanism to describe and detect its own behavior, and can adjust or modify the state and related semantics of the behavior described by the application according to the state and result of its own behavior.

The reflection mechanism in Java is called Reflection. (When you see this word, the first idea should be to search in the development documentation.) It allows the running Java program to check itself and directly manipulate the internal properties or methods of the program. The Reflection mechanism allows the program to use ReflectionAPIs to obtain the internal information of any known-named class, including: package, type parameters, superclass, implemented interfaces, inner classes, outer classes, fields, constructors, methods, modifiers, etc. , And can dynamically generate Instances, change the content of fields or invoke methods during the execution.

Well, to understand this, then we will know that we can use the reflection mechanism to dynamically call some protected or even private methods or classes in the Java program, which can largely meet our special needs. Of course you will ask, what is the use of the reflection mechanism under the Android platform?

When we are developing Android programs, we will download the source code of the corresponding version of AndroidSDK from the Internet in order to facilitate the debugging of the program and quickly locate the error point of the program (here we provide you with a download link of version 2.3.3). You will find that many classes or methods are often marked with "@hide" annotations. Its function is to make this method or class invisible when the SDK is generated. Then our program may not be compiled and passed, and when it is finally released , There may be some problems.

So, for this problem, the first method is to remove the "@hide" mark in the Android source code by yourself, and then recompile to generate an SDK. Another way is to use the Java reflection mechanism, which can be used to access methods with access rights or modify their domains.

Nonsense for a long time, it's time to enter the topic. Before entering the topic, give the code of the previous reflection test class. The code defines the class that we need to reflect. This class has no practical use and is only used as a test class. Tip: The code provided in this article is not the code under the Android platform, but an ordinary Java program, just a Demo program for the Java reflection mechanism, so don’t compile it under Android, otherwise there will be problems, don’t hold me accountable Your responsibility!

package crazypebble.reflectiontest; import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.Serializable;


 public class ReflectionTest extends Object implements ActionListener,Serializable{
 // 成员变量
private int bInt;
 public Integer bInteger = new Integer(4);
 public String strB = "crazypebble";
 private String strA;


 // 构造函数
public ReflectionTest() {


 }


 protected ReflectionTest (int id, String name) { 


 }


 // 成员方法
public int abc(int id, String name) {
 System.out.println ("crazypebble ---> " + id + "-" + name);
 return 0;
 }


 protected static void edf() {


 }


 @Override
 public void actionPerformed(ActionEvent e) {
 // TODO Auto-generated method stub


 }


 }

Second, the classes that need to be used in the reflection mechanism

I list the classes that need to be used in the following table. Among them, the classes that are particularly useful to us are displayed by highlighting them and will be explained step by step in the subsequent use:


Three, Class class

First of all, I want to explain to you that Class itself is a class, and Class is the name of the class. Look at the definition of the following class:

public class MyButton extends Button {...}

Note that the first letter of the above class is lowercase, which represents a class type, but our Class is a class, which is equivalent to the MyButton class defined above. Therefore, do not understand the Class here as a class type. Knowing this, we continue.

Class class is the source of the entire Java reflection mechanism. Class class itself represents the type of Java object. We can get the type of an object through the getClass() method of an Object object. This function returns a Class class. There are many ways to obtain a Class object:

In normal use, pay attention to the flexible use of these methods, especially the use of the Class.forName() method. Because in many developments, objects of the Class class are directly obtained by the name of the class.


Four, get the relevant information of the class

1. Get the construction method

The Class class provides four public methods for obtaining the construction method of a certain class.

Constructor getConstructor(Class[] params) According to the parameters of the constructor, returns a specific constructor with public attributes

Constructor getConstructors() returns an array of all constructors with public attributes

Constructor getDeclaredConstructor(Class[] params) returns a specific constructor according to the parameters of the constructor (regardless of public and non-public attributes)

Constructor getDeclaredConstructors() returns an array of all constructors in this class (regardless of public and non-public attributes)

Since the Java language is an object-oriented language and has a polymorphic nature, we can call different construction methods to create instances of the class through the difference in the parameter list of the construction method. Similarly, to obtain information about different construction methods, it is also necessary to provide corresponding parameter type information; therefore, the above four different ways to obtain construction methods are produced.

/**
 * 获取反射类中的构造方法
* 输出打印格式:"Modifier修饰域 构造方法名(参数类型列表)"
 */
public static void get_Reflection_Constructors( ReflectionTest r) {


 Class temp = r.getClass();
 String className = temp.getName(); // 获取指定类的类名


try {
 Constructor[] theConstructors = temp.getDeclaredConstructors(); // 获取指定类的公有构造方法


for (int i = 0; i < theConstructors.length; i++) {
 int mod = theConstructors[i].getModifiers(); // 输出修饰域和方法名称
System.out.print( Modifier.toString(mod) + " " + className + "(");
 Class[] parameterTypes = theConstructors[ i ].getParameterTypes(); // 获取指定构造方法的参数的集合
for (int j = 0; j < parameterTypes.length; j++) { // 输出打印参数列表
System.out.print( parameterTypes[j].getName());
 if (parameterTypes.length > j+1) {
 System.out.print(", ");
 }
 }
 System.out.println(")");
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

2. Get the member method of the class

Similar to the way of obtaining the constructor, there are four ways of obtaining member methods.

Method getMethod(String name, Class[] params) returns a specific method with public attributes according to the method name and parameters

Method[] getMethods() returns an array of all methods with public attributes

Method getDeclaredMethod(String name, Class[]params) returns a specific method based on the method name and parameters (regardless of public and non-public attributes)

Method[] getDeclaredMethods() returns an array of all methods in the class (regardless of public and non-public attributes)

/**
 * 获取反射类的方法
* 打印输出格式:"RetType FuncName( paramTypeList)"
 */
 public static void get_Reflection_Method( ReflectionTest r) {


 Class temp = r.getClass();
 String className = temp.getName();


 /*
 * Note: 方法getDeclaredMethods()只能获取到由当前类定义的所有方法,不能获取从父类继承的方法
* 方法getMethods() 不仅能获取到当前类定义的public方法,也能得到从父类继承和已经实现接口的public方法
* 请查阅开发文档对这两个方法的详细描述。
*/
 //Method[] methods = temp.getDeclaredMethods();
 Method[] methods = temp.getMethods();


 for (int i = 0; i < methods.length; i++) {


 // 打印输出方法的修饰域
int mod = methods[i].getModifiers();
 System.out.print( Modifier.toString(mod) + " ");


 // 输出方法的返回类型
System.out.print( methods[i].getReturnType().getName()); 


 // 获取输出的方法名
System.out.print(" " + methods[i].getName() + "(");


 // 打印输出方法的参数列表
Class[] parameterTypes = methods[i].getParameterTypes();
 for (int j = 0; j < parameterTypes.length; j++) {
 System.out.print (parameterTypes[j].getName());
 if (parameterTypes.length > j+1) {
 System.out.print(", ");
 }
 }
 System.out.println(")");
 }
 }

When obtaining the member methods of a class, there is one place worthy of everyone's attention, that is, the getMethods() method and the getDeclaredMethods() method.

getMethods(): Used to obtain all the member methods of the public modified domain of the class, including public methods inherited from the parent class and public methods that implement interfaces;

getDeclaredMethods(): Used to get all member methods defined in the current class and implemented interface methods, excluding methods inherited from the parent class.

You can check the explanation of the development document:

getMethods() - Returns an array containing Methodobjects for all public methods for the class C representedby this Class.

Methods may be declared in C, the interfaces it implements or in the superclasses of C.

The elements in the returned array are inno particular order.


getDeclaredMethods() - Returns a Method object which                             represents the method matching the specified nameand parameter types

that is declared by the class representedby this Class.

Therefore, in the method get_Reflection_Method(...) of the sample code, the ReflectionTest class inherits the Object class, implements the actionPerformed method, and defines the following member methods:

The results after the execution of these two statements are different:

a, Method[] methods = temp.getDeclaredMethods() The results after execution are as follows:

b. After Method[] methods = temp.getMethods() is executed, the results are as follows:

3. Get the member variables of the class (member attributes)

There are four ways to get member attributes

Field getField(String name) returns a specific member variable with public attributes according to the variable name

Field[] getFields() returns an array of member variables with public attributes

Field getDeclaredField(String name) returns a member variable based on the variable name (regardless of public and non-public attributes)

Field[] getDelcaredField() returns an array of all member variables (regardless of public and non-public attributes)

/**
 * 获取反射类中的属性和属性值
* 输出打印格式:"Modifier Type : Name = Value"
 * Note: 对于未初始化的指针类型的属性,将不输出结果
*/
public static void get_Reflection_Field_Value( ReflectionTest r) {


 Class temp = r.getClass(); // 获取Class类的对象的方法之一


try {
 System.out.println("public 属性");
Field[] fb = temp.getFields();
 for (int i = 0; i < fb.length; i++) {


 Class cl = fb[i].getType(); // 属性的类型


int md = fb[i].getModifiers(); // 属性的修饰域


Field f = temp.getField(fb[i].getName()); // 属性的值
f.setAccessible(true);
 Object value = (Object)f.get(r);


 // 判断属性是否被初始化
if (value == null) {
 System.out.println( Modifier.toString(md) + " " + cl + " : " + fb[i].getName());
 }
 else {
 System.out.println( Modifier.toString(md) + " " + cl + " : " + fb[i].getName() + " = " + value.toString());
 }
 }


 System.out.println ("public & 非public 属性");
Field[] fa = temp.getDeclaredFields();
 for (int i = 0; i < fa.length; i++) {


 Class cl = fa[i].getType(); // 属性的类型


int md = fa[i].getModifiers(); // 属性的修饰域


Field f = temp.getDeclaredField(fa[i].getName()); // 属性的值
f.setAccessible(true); // Very Important
 Object value = (Object) f.get(r);


 if (value == null) {
 System.out.println( Modifier.toString(md ) + " " + cl + " : " + fa[i].getName());
 }
 else { 
 System.out.println( Modifier.toString(md ) + " " + cl + " : " + fa[i].getName() + " = " + value.toString());
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

4. Get the modified domains of classes, attributes, and methods

The classes Class, Method, Constructor, and Field all have a public method intgetModifiers(). This method returns a number of type int, representing the combined value of the modified type of the modified object (Class, Method, Constructor, Field).

In the development document, you can find that there are several specific modification domains defined in the Modifier class. Each modification domain is a fixed int value. The list is as follows:

This class not only provides a number of methods boolean isXXXXX (intmodifiers) for determining whether a modified domain is owned, but also provides a StringtoString (int modifier) ​​method to convert an int number representing the combined value of a modified domain into a description modified domain String.


Five, how to call the private method in the class

Before the introduction, let's put a code. This code is copied from other articles. The code is not long, but the explanation of the process of dynamically calling the member methods of the class is easy to understand.

package crazypebble.reflectiontest;
import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;


 public class LoadMethod {
 /**
 * 在运行时加载指定的类,并调用指定的方法
* @param cName Java的类名
* @param MethodName 方法名
* @param types 方法的参数类型
* @param params 方法的参数值
* @return
 */
 public Object Load( String cName, String MethodName, String[] types, String[] params) {


 Object retObject = null;


 try {
 // 加载指定的类
Class cls = Class.forName(cName); // 获取Class类的对象的方法之二


// 利用newInstance()方法,获取构造方法的实例
// Class的newInstance方法只提供默认无参构造实例
// Constructor的newInstance方法提供带参的构造实例
Constructor ct = cls.getConstructor(null);
 Object obj = ct.newInstance(null); 
 //Object obj = cls.newInstance();


 // 构建 方法的参数类型
Class paramTypes[] = this.getMethodTypesClass( types);


 // 在指定类中获取指定的方法
Method meth = cls.getMethod( MethodName, paramTypes);


 // 构建 方法的参数值
Object argList[] = this.getMethodParamObject(types, params);


 // 调用指定的方法并获取返回值为Object类型
retObject = meth.invoke(obj, argList);


 } catch (Exception e) {
 System.err.println(e);
 }


 return retObject;
 }


 /**
 * 获取参数类型,返回值保存在Class[]中
*/
public Class[] getMethodTypesClass(String[] types) {
 Class[] cs = new Class[types.length];


 for (int i = 0; i < cs.length; i++) {
 if (types[i] != null || !types[i].trim().equals("")) {
 if (types[i].equals("int") || types[i].equals("Integer")) {
 cs[i] = Integer.TYPE;
 } 
 else if (types[i].equals( "float") || types[i].equals( "Float")) {
 cs[i] = Float.TYPE;
 }
 else if (types[i].equals("double") || types[i].equals("Double")) {
 cs[i] = Double.TYPE;
 }
 else if (types[i].equals("boolean") || types[i].equals("Boolean")) {
 cs[i] = Boolean.TYPE;
 }
 else {
 cs[i] = String.class;
 }
 }
 }
 return cs;
 }


 /**
 * 获取参数Object[]
 */
 public Object[] getMethodParamObject( String[] types, String[] params) {


 Object[] retObjects = new Object[params.length];


 for (int i = 0; i < retObjects.length; i++) {
 if(!params[i].trim().equals("")||params[i]!=null){ 
 if(types[i].equals("int")||types[i].equals("Integer")){ 
 retObjects[i]= new Integer(params[i]); 
 }
 else if(types[i].equals("float")||types[i].equals("Float")){ 
 retObjects[i]= new Float(params[i]); 
 }
 else if(types[i].equals("double")||types[i].equals("Double")){ 
 retObjects[i]= new Double(params[i]); 
 }
 else if(types[i].equals("boolean")||types[i].equals("Boolean")){ 
 retObjects[i]=new Boolean(params[i]); 
 }
 else{ 
 retObjects[i] = params[i]; 
 } 
 } 
 }


 return retObjects;
 }
 }

To call a method of a class, you first need an instance of the class (of course, if the class is static, you don't need an instance, as for the reason, you know!).

1. Create an instance of the class

After getting the Class object of a class, we can use the class Constructor to instantiate the object. Constructor supports generics, that is, it should be Constructor<T>. This class has a public member function: TnewInstance(Object... args), where args is the corresponding parameter. We use this method of Constructor to create an object instance of the class.

In the code LoadMethod.java and LoadMethodEx.java, two methods are given to instantiate the Class class: one is to use the Constructor class to call the newInstance() method; the other is to use the newInstance() method of the Class class itself to create An example. The effect of the two methods is the same.

// 利用newInstance()方法,获取构造方法的实例
// Class的newInstance方法,仅提供默认无参的实例化方法,类似于无参的构造方法
// Constructor的newInstance方法,提供了带参数的实例化方法,类似于含参的构造方法 
Constructor ct = cls.getConstructor(null);
Object obj = ct.newInstance(null);
Object obj = cls.newInstance();

2. Behavior

The Method class contains information about the member methods of the class. There is a public member function in the Method class: Object invoke(Object receiver, Object... args), the parameter receiver indicates the calling object, and the parameter args indicates the parameters that the method needs to receive. Since we dynamically call the method of the class at runtime, we cannot know the parameter type and return value type of the class in advance, so the type of the passed parameter is Object, and the type returned is also Object. (Because the Object class is the parent class of all other classes)

If a method is a static method of a Java class, then the Object receiver parameter can be passed in null, because static methods never belong to objects.

3. Properties

To read and write the member variables of the class, there are two public methods in the Field class:

Object get(Object object), this method can be used to get the value of a member variable

Void set(Object object, Object value), this method sets the value of a member variable

Among them, the Object parameter is the object that needs to be passed in; if the member variable is a static property, null can be passed in the object.


Six, optimization of LoadMethod.java

In the LoadMethod.java given in the previous section, the class LoadMethod calls the method of fixed parameter type, and the parameter type is passed in through an array of String[], and then parsed by the method getMethodTypesClass(). The specific type of the parameter. At the same time, in the getMethodTypesClass() and getMethodParamObject() methods, after filtering the incoming string parameters, the parameter types that can be matched are processed, and the other parameters that cannot be matched are processed as String objects. If the parameters required by the method we call are not simple variables, but custom class objects, or List lists, and if we only know the class name and method name, but don’t know the parameter types of the method, how should we deal with these What about the situation?

Therefore, I optimized the LoadMethod class. Attach the code first:

package crazypebble.reflectiontest;
import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;


 public class LoadMethodEx {
 /**
 * 在运行时加载指定的类,并调用指定的方法
* @param cName Java的类名
* @param MethodName 方法名
* @param params 方法的参数值
* @return
 */
 public Object Load(String cName, String MethodName, Object[] params) {


 Object retObject = null;


 try {
 // 加载指定的类
Class cls = Class.forName(cName); // 获取Class类的对象的方法之二


// 利用newInstance()方法,获取构造方法的实例
// Class的newInstance方法只提供默认无参构造实例
// Constructor的newInstance方法提供带参的构造实例
Constructor ct = cls.getConstructor(null);
 Object obj = ct.newInstance(null); 
 //Object obj = cls.newInstance();
 // 根据方法名获取指定方法的参数类型列表
Class paramTypes[] = this.getParamTypes(cls, MethodName);


 // 获取指定方法
Method meth = cls.getMethod(MethodName, paramTypes);
 meth.setAccessible(true);


 // 调用指定的方法并获取返回值为Object类型
retObject = meth.invoke(obj, params);


 } catch (Exception e) {
 System.err.println(e);
 }


 return retObject;
 }


 /**
 * 获取参数类型,返回值保存在Class[]中
*/
public Class[] getParamTypes (Class cls, String mName) {
 Class[] cs = null;


 /*
 * Note: 由于我们一般通过反射机制调用的方法,是非public方法
* 所以在此处使用了getDeclaredMethods()方法
*/
Method[] mtd = cls.getDeclaredMethods(); 
 for (int i = 0; i < mtd.length; i++) {
 if (!mtd[i].getName().equals(mName)) { // 不是我们需要的参数,则进入下一次循环
continue;
 }


 cs = mtd[i].getParameterTypes();
 }
 return cs;
 }
 }

Through a series of analysis in the previous sections, as long as we know the class name of a class (including its package path), then we can obtain the member variables, construction methods, and members of the class through a series of methods of the Class class Methods, as well as the parameter types and return types of member methods, as well as information about modified fields.

If we already know the name of a certain class and the name of the method that needs to be dynamically called, how can we call the method without passing in the parameter type of the method?

In the case of a known class name, we can print out all the information of the class, of course, including the member methods of the class; and then filter the printed method names through the given method name to find the method we need; Through the Method object of the method, the parameter type, parameter number, and return type of the method are obtained. Then when we dynamically call the method externally, we don't need to care about the type of parameters that the class needs to pass in, but only need to pass in the information of the class name, method name, and parameter value. The author implements a class LoadMethodEx, and first compares the parameters required by the same method of the two classes:

1. The LoadMethodEx class lacks a parameter (method parameter type list). This article directly obtains the parameter type list from the LoadMethod class, and does not require the user to input this information. The benefits are self-evident.

2. The parameter value of the method: The LoadMethod class is to pass in all method parameters as a String, and then parse it after passing in; and this article directly uses the Object type as the parameter type, because invoke(Objectobj, Object. ..args) The parameter type required by the method itself is Object, which avoids unnecessary parameter type conversion.

When calling the Load() method of LoadMethod, the user only needs to know the class name and method name, and the initialized parameters are first converted to Object, and then passed to the Load() method. The return value of the method is Object, which must be converted to the type required by the user according to his needs.

public 属性
public class java.lang.Integer : bInteger = 4
 public class java.lang.String : strB = crazypebble
 public & 非public 属性
private int : bInt = 0
 public class java.lang.Integer : bInteger = 4
 public class java.lang.String : strB = crazypebble
 private class java.lang.String : strA
构造方法:
public crazypebble.reflectiontest.ReflectionTest()
 protected crazypebble.reflectiontest.ReflectionTest(int, java.lang.String)
父类/接口:
 父类: java.lang.Object
接口0: java.awt.event.ActionListener
接口1: java.io.Serializable
成员方法:
public int abc(int, java.lang.String)
 public void actionPerformed( java.awt.event.ActionEvent )
 public final native void wait(long)
 public final void wait()
 public final void wait(long, int)
 public boolean equals(java.lang.Object)
 public java.lang.String toString()
 public native int hashCode()
 public final native java.lang.Class getClass()
 public final native void notify()
 public final native void notifyAll()
反射机制调用方法:LoadMethod
 crazypebble ---> 1-hello, android-1!
反射机制调用方法:LoadMethodEx
 crazypebble ---> 2-hello, android-2?
返回结果:0

Seven, summary

Regarding the reflection mechanism, there is actually a more sensitive topic, that is, the reflection mechanism brings us security issues. Since I have not studied this aspect very deeply, it is not good to speak.
The source code of the program:

package crazypebble.androidreflection;
import java.lang.reflect.Field;
import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
public class MainActivity extends Activity {
 /** Called when the activity is first created. */
 private static Button btnHandler = null;
 private static Button btnShowing = null;
 AlertDialog alertDialog = null;


 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);


 btnHandler = (Button)findViewById( R.id.btn_mHandler);
 btnHandler.setOnClickListener(new ButtonListener());


 btnShowing = (Button)findViewById( R.id.btn_mShowing);
 btnShowing.setOnClickListener( new ButtonListener());


 alertDialog = new AlertDialog.Builder(this)
 .setTitle("abc")
 .setMessage("Content")
 .setIcon(R.drawable.icon)
 .setPositiveButton("确定", new PositiveClickListener())
 .setNegativeButton("取消", new NegativeClickListener())
 .create();
 }


 private class ButtonListener implements OnClickListener {
 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.btn_mHandler:
 modify_mHandler();
 alertDialog.show();
 break;
 case R.id.btn_mShowing:
 alertDialog.show();
 break;
 default:
 break;
 }
 }
 }


 private class PositiveClickListener implements android.content.DialogInterface .OnClickListener {
 @Override
 public void onClick( DialogInterface dialog, int which ) {
 // 方法二时启用
modify_dismissDialog(false);
 }
 }


 private class NegativeClickListener implements android.content.DialogInterface.OnClickListener {
 @Override
 public void onClick( DialogInterface dialog, int which ) {
 // 方法一时启用
//dialog.dismiss();
 // 方法二时启用
modify_dismissDialog(true);
 }
 }


 /*
 * 第一种方法:修改AlertController类的private成员变量mHandler的值
*/
public void modify_mHandler() {
 try {
 Field field = alertDialog.getClass( ).getDeclaredField("mAlert");
 field.setAccessible(true);
 // 获取mAlert变量的值
Object obj = field.get(alertDialog);
 field = obj.getClass().getDeclaredField("mHandler");
 field.setAccessible(true);
 // 修改mHandler变量的值,使用新的ButtonHandler类
field.set(obj, new MyButtonHandler(alertDialog));


 } catch (Exception e) {
 e.printStackTrace();
 }
 }


 /*
 * 第二种方法:修改dismissDialog()方法
*/
public void modify_dismissDialog(boolean flag) {
 try {
 Field field = alertDialog.getClass( ).getSuperclass( ).getDeclaredField("mShowing");
 field.setAccessible(true);
 // 将mShowing变量设为false,表示对话框已经关闭
field.set(alertDialog, flag);
 alertDialog.dismiss();
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 }
package crazypebble.androidreflection;
import java.lang.ref.WeakReference;
import android.content.DialogInterface;
 import android.os.Handler;
 import android.os.Message;
public class MyButtonHandler extends Handler{
 // Button clicks have Message.what as the BUTTON{1,2,3} constant
 private static final int MSG_DISMISS_DIALOG = 1;


 private WeakReference<DialogInterface> mDialog;
 public MyButtonHandler( DialogInterface dialog) {
 mDialog = new WeakReference <DialogInterface>(dialog);
 }
 @Override
 public void handleMessage( Message msg) {
 switch (msg.what) {


 case DialogInterface.BUTTON_POSITIVE:
 case DialogInterface.BUTTON_NEGATIVE:
 case DialogInterface.BUTTON_NEUTRAL:
 ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
 break;
 }
 }
 }

After reading the above article, I hope you can be clear: the reflection mechanism can get the private methods and properties of a class through the voidsetAccessible(booleanflag) method. Using these private methods and properties, you can already do something beyond the limit. Up. So you need to be cautious when using it!


Previous wonderful recommendations

Summary of Tencent, Ali, Didi Backstage Interview Questions-(including answers)

Interview: The most comprehensive multi-threaded interview questions in history!

The latest Alibaba pushes Java back-end interview questions

JVM is difficult to learn? That's because you didn't read this article seriously

—END—

Follow the author's WeChat public account—"JAVA Rotten Pigskin"

Learn more about java back-end architecture knowledge and the latest interview book

Every thing you order is pretty, I take it seriously as a favorite

After reading this article, remember to give the author a thumbs up + watching it~~~ Everyone's support is the motivation for the author to continue publishing articles.

Guess you like

Origin blog.csdn.net/yunzhaji3762/article/details/108958090