01、反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
02、反射作用
- 反编译:将 class 文件反编译成 Java 文件。
- 访问对象:访问 Java 对象中的属性、方法、构造方法等。
03、需要使用的类
- java.lang.Class - 类,某个具体的类或接口
- java.lang.reflect.Constructor - 反射构造方法
- java.lang.reflect.Field - 反射属性
- java.lang.reflect.Method - 反射方法
- java.lang.reflect.Modifier - 访问修饰符的信息
04、获取 Class 对象的三种方法
- Class.forName 方式,会让ClassLoader装载类,并进行类的初始化
- .class 方式,ClassLoader 装载入内存,不对类进行类的初始化操作
- 3、getClass 方式,返回类对象运行时真正所指的对象,所属类型的Class对象
区别主要在于是否进行初始化和是否在实例中获取
// 1、Class.forName 方式,会让ClassLoader装载类,并进行类的初始化
try {
Class> c1 = Class.forName("com.zpan.reflecttest.ReflectTest");
Log.e("zpan", "c1 == " + c1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 2、.class 方式,ClassLoader 装载入内存,不对类进行类的初始化操作
Class c2 = ReflectTest.class;
Log.e("zpan", "c2 == " + c2);
// 3、getClass 方式,返回类对象运行时真正所指的对象,所属类型的Class对象
Class c3 = new ReflectTest().getClass();
Log.e("zpan", "c3 == " + c3);
Log
c1 == class com.zpan.reflecttest.ReflectTest
c2 == class com.zpan.reflecttest.ReflectTest
c3 == class com.zpan.reflecttest.ReflectTest
05、获取构造函数(四个方法)
反射类构造函数
public ReflectTest() { }
public ReflectTest(String str) { }
private ReflectTest(String str1, String str2) { }
获取构造函数
- getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
- getConstructors() 返回所有具有public属性的构造函数数组
- getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
- getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
Class c2 = ReflectTest.class;
// 1、getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
try {
Constructor constructor1 = c2.getConstructor(String.class);
Log.e("zpan", "constructor1 ==" + constructor1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 2、getConstructors() 返回所有具有public属性的构造函数数组
Constructor[] constructors1 = c2.getConstructors();
for (int i = 0; i < constructors1.length; i++) {
Log.e("zpan", "constructors1 =" + i + "=" + constructors1[i]);
}
// 3、getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
try {
Constructor constructor2 = c2.getDeclaredConstructor(String.class, String.class);
Log.e("zpan", "constructor2 ==" + constructor2);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 4、getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
Constructor[] constructors2 = c2.getDeclaredConstructors();
for (int i = 0; i < constructors2.length; i++) {
Log.e("zpan", "constructors2 =" + i + "=" + constructors2[i]);
}
Log
constructor1 ==public com.zpan.reflecttest.ReflectTest(java.lang.String)
constructors1 =0=public com.zpan.reflecttest.ReflectTest()
constructors1 =1=public com.zpan.reflecttest.ReflectTest(java.lang.String)
constructor2 ==private com.zpan.reflecttest.ReflectTest(java.lang.String,java.lang.String)
constructors2 =0=public com.zpan.reflecttest.ReflectTest()
constructors2 =1=public com.zpan.reflecttest.ReflectTest(java.lang.String)
constructors2 =2=private com.zpan.reflecttest.ReflectTest(java.lang.String,java.lang.String)
06、获取反射对象
注:
- newInstance() 方法返回的是一个泛型T,我们要强转成相应的反射类。
- 反射创建对象,可以使用Class.newInstance() 和 Constructor.newInstance() 两种方式,而前者必须要求反射类中存在一个无参的构造方法,并且有访问权限;后者适应各种类型的构造方法,无论是否有参数都可以调用,这是需要 setAccessible() 控制访问验证即可。一般建议是使用后者。
// 无参构造创建对象
try {
ReflectTest r2 = (ReflectTest) c2.newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
// 有参构造创建对象
try {
ReflectTest reflectTest = (ReflectTest) constructor1.newInstance("zpan");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
07、获取反射类的方法(四个方法)
反射类方法
public void testPublicVoidMethod() { }
public String testPublicStringMethod() {
return "";
}
private void testPrivateVoidMethod() { }
- getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
- getMethods() 返回所有具有public属性的方法数组
- getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
- getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
Class c2 = ReflectTest.class;
// 1、根据方法名和参数,返回一个具体的具有public属性的方法
try {
Method method1 = c2.getMethod("testPublicVoidMethod", null);
Log.e("zpan", "method1 ==" + method1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 2、返回所有具有public属性的方法数组
Method[] methods1 = c2.getMethods();
for (int i = 0; i < methods1.length; i++) {
Log.e("zpan", "methods1 =" + i + "=" + methods1[i]);
}
// 3、根据方法名和参数,返回一个具体的方法(不分public和非public属性)
try {
Method method2 = c2.getDeclaredMethod("testPrivateVoidMethod", null);
Log.e("zpan", "method2 ==" + method2);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 4、返回该类中的所有的方法数组(不分public和非public属性)
Method[] methods2 = c2.getDeclaredMethods();
for (int i = 0; i < methods2.length; i++) {
Log.e("zpan", "methods2 =" + i + "=" + methods2[i]);
}
Log
method1 ==public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()
methods1 =6=public java.lang.String com.zpan.reflecttest.ReflectTest.testPublicStringMethod()
methods1 =7=public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()
method2 ==private void com.zpan.reflecttest.ReflectTest.testPrivateVoidMethod()
methods2 =1=private void com.zpan.reflecttest.ReflectTest.testPrivateVoidMethod()
methods2 =2=public java.lang.String com.zpan.reflecttest.ReflectTest.testPublicStringMethod()
methods2 =3=public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()
从日志中可以看出methods1 下标出现6、7,而methods2 下标是1、2、3
- getMethods():用于获取类的所有的public修饰域的成员方法,包括从父类继承的public方法和实现接口的public方法;
- getDeclaredMethods():用于获取在当前类中定义的所有的成员方法和实现的接口方法,不包括从父类继承的方法。
08、获取反射类的属性(四个方法)
反射类属性
public String mPublicStr;
public int mPublicInt;
private String mPrivateStr;
protected String mProtectedStr;
- getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
- getFields() 返回具有public属性的成员变量的数组
- getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
- getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
Class c2 = ReflectTest.class;
// 1、getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
try {
Field field1 = c2.getField("mPublicStr");
Log.e("zpan", "field1 ==" + field1);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 2、getFields() 返回具有public属性的成员变量的数组
Field[] fields1 = c2.getFields();
for (int i = 0; i < fields1.length; i++) {
Log.e("zpan", "fields1 =" + i + "=" + fields1[i]);
}
// 3、getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
try {
Field field2 = c2.getDeclaredField("mProtectedStr");
Log.e("zpan", "field2 ==" + field2);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 4、getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
Field[] fields2 = c2.getDeclaredFields();
for (int i = 0; i < fields2.length; i++) {
Log.e("zpan", "fields2 =" + i + "=" + fields2[i]);
}
Log
field1 ==public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr
fields1 =0=public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr
fields1 =1=public int com.zpan.reflecttest.ReflectTest.mPublicInt
fields1 =2=public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr
field2 ==public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr
fields2 =0=private java.lang.String com.zpan.reflecttest.ReflectTest.mPrivateStr
fields2 =1=public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr
fields2 =2=public int com.zpan.reflecttest.ReflectTest.mPublicInt
fields2 =3=public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr
09、获取类、属性、方法的修饰符
通过 int getModifiers() 方法获得修饰符,方法返回是是一个 int 型数值,每个修饰符都对应一个int型。
10、反射框架
JOOR
参考文章
Java反射机制的原理及在Android下的简单应用
Android 反射机制的理解
Android中反射的简单应用