Java反射机制

学习Java反射机制

Java的类对象

类对象:所有定义的类,都有一个对应的类对象。这个类对象用于提供类本身的信息,比如有几种构造方法,有多少字段属性,有多少普通方法。

获取类对象的方法有:

  • Class.forName(要获取的类名称)
  • 类名称.class
  • new 类构造函数().getClass()
    在一个JVM中,一个类只会有一个类对象存在,所以以上三种获取到的类对象都是一样的。

在获取类对象的时候,会导致类属性被初始化,即类中所有属性都会运行。

反射机制

与传统的通过new来创建对象实例不同,反射机制,会首先拿到要创建的类的类对象,然后通过类对象获取”构造对象“。在通过构造对象创造对象。

通过constructor创造对象

  • Class pClass = Class.forName(类名)
  • Constructor constructor = pClass.getConstructor();
  • Hero hero = (Hero) constructor.newInstance();

通过类对象获取类字段

  • getField(name) 只能获取public,从父类继承得来的字段
  • getDeclaredField(name) 可以获取本类的所有字段,包括private,但不能获取继承字段。注意,能够获取private字段但并不能修改private字段,除非加上setAccessible(true)

通过反射机制调用函数

  • Method method = object.getClass().getMethod(methodName, Args.getClass())
  • method.invoke(object, args)
    注意getMethod中args.getClass必须是函数中定义的形式,如果涉及到子类父类继承的话不能自动探索传入参数的类型。

Tips:
假设现在有
ADHero h1 继承自父类Hero
那么
Hero hero = (Hero) h1;
这个时候hero.getClass()仍然会返回ADHero。
但是将h1传一个接收参数为Hero的函数的时候时候,就自动向上转换成了父类。

反射机制有什么用

在使用Spring框架的时候如果要切换两个业务之间的代码,不需要整个修改所有的代码,只需要将配置文件进行修改就可以实现两个业务代码之间的切换。

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
package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
* @author shaoguoliang
*
*/
public class TestReflection {
public static void main(String[] args){
//传统方式创建
Hero hero1 = new Hero();
hero1.name = "GS";
System.out.println(hero1);

//通过反射机制创建
try {
String className = "reflection.Hero";
//获取类对象
Class pClass = Class.forName(className);
//构造器
Constructor constructor = pClass.getConstructor();
//通过构造器实例化
Hero hero2 = (Hero) constructor.newInstance();
hero2.name = "GS2";
System.out.println(hero2);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}

//通过反射机制修改hero.name
try {
Field f1 = hero1.getClass().getDeclaredField("name");
f1.set(hero1, "changedGS");
System.out.println(hero1.name);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//通过反射机制调用类函数
try {
Method method = hero1.getClass().getMethod("setName", String.class);
method.invoke(hero1, "sgl");
System.out.println(hero1.name);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}