Java的反射机制

Java的反射机制

薛定谔的汪

Java反射机制是Java语言被视为准动态语言的关键性质。Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调用其方法或修改其域(甚至是本身声明为private的域或方法)。很多主流框架使用了反射,如典型的Spring的IOC(控制反转)、读取properties文件内容等

Class类是整个Java反射机制的源头,因此,要想使用Java反射,我们首先得到Class类的对象。

准备好一个实体类:

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
/**
* @Auther: ZhengYakai
* @Description: 实体类
* @Date: Create in 2017/10/26
* @Modify:
*/
public class User {

private Integer id;
private String name;
private Integer age;

public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}

public User() {

}
private void say(String word){
System.out.println(word);
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}

获取Class的方式:

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
/**
* @Auther: ZhengYakai
* @Description: 获取class的方式
* @Date: Create in 2017/10/26
* @Modify:
*/
public class ReflectDemo {

public static void main(String[] args) {
try {
//方式1
Class<User> userClass1 = User.class;
//方式2 较常用
Class<?> userClass2 = Class.forName("com.yakai.bean.User");
User user = new User();
//方式3
Class<? extends User> userClass3 = user.getClass();
System.out.println(userClass1);
System.out.println(userClass2);
System.out.println(userClass3);
//方式4 适用于基本类型的包装类型
Integer i = 4;
Boolean b =false;
Class<Integer> iClass = i.TYPE;
Class<Boolean> bClass = b.TYPE;
System.out.println(iClass);
System.out.println(bClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

操作class对象:

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
/**
* @Auther: ZhengYakai
* @Description: 操作class对象
* @Date: Create in 2017/10/26
* @Modify:
*/
public class ReflectDemo2 {
public static void main(String[] args) {

try {
Class<?> userClass = Class.forName("com.yakai.bean.User");
//获得实例对象
Object o = userClass.newInstance();
User user=null;
if(o instanceof User){
user= (User) o;
}
System.out.println(user);
//获取Person的属性,两种方式,一种是获取属性数组,一种是获取指定属性
//加Declared是获取所有属性,但是不包括父类继承过来的
//不加Declared是获取公有的,包括父类继承过来的
//访问私有属性需要setAccessible为true
Field[] fields = userClass.getDeclaredFields();
Field nameField = userClass.getDeclaredField("name");


//获取User方法 与获取属性相似
Method[] declaredMethods = userClass.getDeclaredMethods();
Method setName = userClass.getDeclaredMethod("setName", String.class);
//执行方法
setName.invoke(user,"zhangsan");
System.out.println(user.getName());

//获得私有方法say
Method say = userClass.getDeclaredMethod("say",String.class);
say.invoke(user, "helloworld");
//获取User的构造方法
Constructor<?>[] constructors = userClass.getConstructors();
//无参构造
Constructor<?> constructor = userClass.getConstructor();
System.out.println(constructor);
//有参构造
Constructor<?> constructor2 = userClass.getConstructor(Integer.class, String.class, Integer.class);
System.out.println(constructor2);
//获取用户实现的接口
Class<?>[] interfaces = userClass.getInterfaces();
} catch (Exception e) {
e.printStackTrace();
}
}
}

执行say.invoke(user, "helloworld");报错!错误信息:

1
2
3
4
5
6
java.lang.IllegalAccessException: Class com.yakai.demo.ReflectDemo2 can not access a member of class com.yakai.bean.User with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:490)
at com.yakai.demo.ReflectDemo2.main(ReflectDemo2.java:44)

这是因为如果要执行private修饰的方法,必须要say.setAccessible(true);才可以

添加这行代码后再执行:

1
2
3
4
5
com.yakai.bean.User@1b6d3586
zhangsan
helloworld //say方法执行。。。
public com.yakai.bean.User()
public com.yakai.bean.User(java.lang.Integer,java.lang.String,java.lang.Integer)

同样对于私有属性Field来说,也是需要field.setAccessible(true);才可以调用私有属性。

JAVA反射的再次学习,灵活的运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加。

  • Title: Java的反射机制
  • Author: 薛定谔的汪
  • Created at : 2017-03-25 19:04:27
  • Updated at : 2023-11-17 19:37:37
  • Link: https://www.zhengyk.cn/2017/03/25/java/Reflect/
  • License: This work is licensed under CC BY-NC-SA 4.0.