java反射介绍
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。主要类包括以下1
2
3
4
5
6
7java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
Class作用是通过类加载机制把相关类加载到虚拟机并返回Object对象句柄
Field对Object的所有属性进行修改和访问
Method对Object的所有方法进行访问
Modifier返回类或者其成员的访问修饰符
直接建立例子学习,说明在代码注释上,哈哈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
79package reflect;
public class Student {
private int id = 1;
private int age = 23;
private String name = "Lin";
protected int gade = 80;
private Funning mFun = new Funning("pingpong");
String dec = "good student";
public static Student getInstance() {
return new Student();
}
public Student(int age, String name, Funning mFun) {
super();
this.age = age;
this.name = name;
this.mFun = mFun;
}
public void show() {
System.out.print(" id=" + id + " name = " + name + " age = " + age + " funning = " + mFun.getName() + " gede = "
+ gade + " " + " dec=" + dec);
}
public Student() {
super();
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Funning getmFun() {
return mFun;
}
public void setmFun(Funning mFun) {
this.mFun = mFun;
}
private class Funning {
private String name;
public Funning(String fun) {
name = fun;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
基本的测试代码为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public static void main(String[] args) {
// TODO Auto-generated method stub
try {
//通过绝对的类名路劲加载类
Class student_class = Class.forName("reflect.Student");
//获取类的指定构造函数,其中int类型的为int.class而不Integer.class,而对于构造函数里面含有内部类,Funning为Student的内部类,所以完整的类名路劲为Student的绝对路径“reflect.Student”+“$”+内部类名
Constructor student_constructor = student_class.getConstructor(int.class, String.class,Class.forName("reflect.Student$Funning"));
//内部类的加载
Class funning_class = Class.forName("reflect.Student$Funning");
//内部类的构造函数默认都有对其外部类的指针,所以构造函数的第一个参数默认值为其寄存的类
Constructor funning_constructor = funning_class.getConstructor(student_class,String.class);
//先实例化内部类还是先实例外部类需要根据实际情况分析,若外部类需要根据内部类的数据提供支撑先就先实例内部类,否则实例外部类
Object funning = funning_constructor.newInstance(null,"basketball");
Object student = student_constructor.newInstance(23,"LZH",funning);
if (student != null) {
//反射Sudent的方法show,getMethod返回的是修饰符为public的方法,getDeclaredMethod不区分修饰符
Method show = Student.class.getDeclaredMethod("show");
//运行Sudent的公有方法show
show.invoke(student);
}
} catch (Exception e) {
e.printStackTrace();
}
}
默认输出结果为
id=1 name = Lin age = 23 funning = pingpong gede = 80 dec=good student
1 访问私有类并改变其属性,把funning的输出由pingpong改成football
1 | public static void main(String[] args) { |
输出结果为:
id=1 name = LZH age = 23 funning = football gede = 80 dec=good student
注意:
1 静态变量或方法的反射,直接在set(Object,Object)或者get(Object,Object)或者invoke(Object,…parameter)等第一个表示实例对象的参数设置为null就行
2 final变量的修饰由于在代码编译过程会直接被替换,比如1
2
3
4
5
6final int i = 1;
int j = i + i;
编译会回直接变成
final int i = 1;
int j = 1 + 1;
android 通过反射修改Toast的显示层级,由WindowManager.LayoutParams.TYPE_TOAST 提升到WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,即使锁屏也可以看到Toast提示
1 | try{ |
所以final的属性的反射暂时发现是不能修改的,若有更好的方法欢迎大家提出,谢谢