Java反射基础总结

在android中Google很多类的某些方法不让第三方应用去调用。
怎么办呢?

反射 (Reflection) 是Java编程语言中的一个功能。

它允许运行中的 Java 程序:

  • 对于任意一个类,都能够知道这个类的所有属性和方法
  • 对于任意一个对象,都能够调用它的任意一个方法和属性。

类的组成模块

类模块 说明
Package Class 对应的包名
Import Class 导入那些classes
Class Class 类,具体的类或接口
Object 每个Class都是Object作为超类
Constructor Class的构造方法
Field 提供Class或接口的属性信息,以及对它动态访问权限
Method 提供Class或接口上的方法信息
Modifier 封装了Classs (methods 方法、fields 属性)的修饰域 (public private protected static final 等)
Class name or Interface name 类的名称 接口名称
Type parameters (构造方法 或 成员方法) 的参数类型
Base class 该类的基类
Implemented interfaces 实现的有那些interfaces(接口)
Inner classes 内部 classes
Outer class 如果当前class本身是inner class,那么它会有一个outer class

获取Class对象的方法

获取 Class对象的方法 示例
getClass() String str =”str”;
Class c=str.getClass();
Class.getSuperclass() Button btn = new Button();
Class c1 = btn.getClass();
Class c2=c1.getSuperClass();
Class.forName() Class c1=Class.forName(“android.widget.Button”);
Class c2 = Class.forName(“java.lang.String”);
.class Class c1 = int.class;
Class c2=int[].class;
Class c3=android.widget.Button.class;
基本类型包装类的TYPE语法 Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;

获取Class对象的相关信息

获取构造方法

  • Constructor getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
  • Constructor getConstructors() 返回所有具有public属性的构造函数数组
  • Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
  • Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
  • 获取构造方法示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    public static String get_Reflection_Constructors(Class cls) {
    String msg = "";
    Class temp = cls;
    String className = temp.getName();// 获取指定类的类名
    try {
    //getDeclaredConstructors 方式获取所有构造
    Constructor[] theConstructors = temp.getDeclaredConstructors();
    for (int i = 0; i < theConstructors.length; i++) {
    int mod = theConstructors[i].getModifiers(); // 修饰域和方法名称
    msg += Modifier.toString(mod) + " " + className + "(";
    Class[] parameterTypes = theConstructors[i].getParameterTypes(); // 获取指定构造方法的参数的集合
    for (int j = 0; j < parameterTypes.length; j++) { // 输出打印参数列表
    msg += parameterTypes[j].getName();
    if (parameterTypes.length > j + 1) {
    msg += ", ";
    }
    }
    msg += ")\n";
    }
    //getConstructor方法获取构造
    Constructor atheConstructors = temp.getConstructor(int.class);
    if(atheConstructors!=null) {
    int mod = atheConstructors.getModifiers(); // 输出修饰域和方法名称
    msg += Modifier.toString(mod) + " " + className + "(";
    Class[] parameterTypes = atheConstructors.getParameterTypes(); // 获取指定构造方法的参数的集合
    for (int j = 0; j < parameterTypes.length; j++) { // 输出打印参数列表
    msg += parameterTypes[j].getName();
    if (parameterTypes.length > j + 1) {
    msg += ", ";
    }
    }
    msg += ")\n";
    }


    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    return msg;
    }
    }

获取类的成员方法

获取类的方法
  • Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
  • Method[] getMethods() 返回所有具有public属性的方法数组
  • Method getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
  • Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
  • 注意:
    • getMethods():用于获取类的所有的public修饰域的成员方法,包括从父类继承的public方法和实现接口的public方法;
    • getDeclaredMethods():用于获取在当前类中定义的所有的成员方法和实现的接口方法,不包括从父类继承的方法。
获取类的属性
  • Field getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
  • Field[] getFields() 返回具有public属性的成员变量的数组
  • Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
  • Field[] getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
获取类、属性、方法的修饰域
  • int getModifiers() 该方法返回一个int类型的数,表示被修饰对象( Class、 Method、 Constructor、 Field )的修饰类型的组合值
  • boolean isXXXXX(int modifiers) 用于判断是否拥有某中修饰域的方法
  • String toString(int modifier) 用于将一个表示修饰域组合值的int数转换成描述修饰域的字符串。
  • 注意:
    • Modifier类中定义了若干特定的修饰域主要有:public、private、protected、static、final、abstract、interface
    • 每个修饰域都是一个固定的int数值
调用类中的方法
创建一个类的实例
  • 要调用一个类的方法,首先需要一个该类的实例(当然,如果该类是static,就不需要实例了)
  • 调用Class 的 方法 : T newInstance(Object… args)
  • Constructor类调用方法:newInstance()
    1
    2
    3
    Constructor ct = cls.getConstructor(null);
    Object obj = ct.newInstance(null);
    Object obj = cls.newInstance();
执行该类的方法
  • Method类提供 Object invoke(Object receiver, Object… args)【参数receiver指明了调用对象,参数args指明了该方法所需要接收的参数。由于我们是在运行时动态的调用类的方法,无法提前知道该类的参数类型和返回值类型,所以传入的参数的类型是Object,返回的类型也是Object。(因为Object类是所有其他类的父类)】
    • 如果某一个方法是Java类的静态方法,那么Object receiver参数可以传入null,因为静态方法从不属于对象。
  • Field类提供
    • Object get(Object object),该方法可用于获取某成员变量的值
    • Void set(Object object, Object value),该方法设置某成员变量的值
    • set(array, 0, “Hello”); //等价于array[0] = “Hello”
  • 注意:
    • 需要调用setAccessible(true);可以执行
    • 其中,Object参数是需要传入的对象;如果成员变量是静态属性,在object可传入null。
调用类中的方法示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
LoadMethod.java
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;
}
}

参考博客