2020年5月19日更新
回看三年前的文章,有很多地方并没有理解到位,本想新写一篇博客但是觉得既然是反射主题不如优化之前的博客,就不再另开新文章了。
反射的用途
通过字节码动态获取对象,调用或修改对象的属性,调用对象的方法
举例来理解吧,android项目有主模块app和library模块,app依赖library模块
app模块有个类叫做UserInfo
public class UserInfo {
public static String getUserName() {
return "Gerry_Liang";
}
}
library模块有个类叫做
public class UserInit {
public static void initName(){
// 在这里要获取UserInfo.getUserName()
}
}
- Library模块里面的UserInit类如何调用app里面的UserInfo类呢?
我们在library里面尝试去使用UserInfo是会报错找不到UserInfo的,因为你并没有依赖app,无法获取app里面的类
1 类名
c.getName()
注意获取的类名是demo1.Person而不是Person
2 构造方法
Constructor[] fs = c.getDeclaredConstructors();
注意构造器的名字是demo1.Person而不是Person
3 属性
Field[] f = c.getDeclaredFields();
注意getDeclaredFields()与getFields()区别是前者是获取所有的属性(无论是private还是public都可以获取),后者只能获取public的属性(其他访问属性都不可以)
4 获取属性的数据类型
field.getType()
注意返回类型是class java.lang.String,int而不是String 和int
5 获取属性/方法的访问修饰符
field.getModifiers()
注意 :虽然方法名有s但是返回的是一个int值,为什么要加s?因为修饰符可能不止一个,如果不止一个就将所有的修饰符对应的数值求和返回
1 表示public
2表示private
4表示protected
8表示static
16表示final
32表示SYNCHRONIZED
64表示VOLATILE
128表示TRANSIENT
256表示NATIVE
512表示INTERFACE
1024表示abstract
2048表示STRICT
(后面的修饰符是隐藏的,我们使用“.”是"."不出来的)
举例:public static final = 1+8+16=25
所以对于一个类中的静态常量来说,其修饰符返回值是25
6 方法
Method[] f= c.getDeclaredMethods();
7 给属性赋值
Field m = fs[i];
m.setAccessible(true);
m.set(person,“haha”);
8 调用类的方法
Method m = fs[i];
m.setAccessible(true);
if(m.getName().contains(“set”)){
m.invoke(person, “lcj”);
}
9 接下来我们把Person类修改下
如何获取Person类的父类或者父接口呢?
Type[] interfaces = Class.forName(“demo1.Person”).getInterfaces();
Class s = Class.forName(“demo1.Person”).getSuperclass();
注意这里获取的接口或者类名都是“包名.类名/接口名”
10 假如Person类是一个空的类呢?
public class Person {
}
这个时候获取该类的构造器,属性,和方法会是什么效果呢?
全部采用xxDeclaredxx方法
该类默认具有1个access$super方法,2个构造器,2个属性