设计模式中,有很多地方会用到反射机制,下面通过代码来讲解反射机制。
一个实体类如下:
1 package springBootExample.example.application;
2
3 public class ReflectApp {
4
5 private String name;
6
7 public String title;
8
9 public ReflectApp() {
10
11 }
12
13 public ReflectApp(String name, String title) {
14 this.name = name;
15 this.title = title;
16 }
17
18 public String getName() {
19 return name;
20 }
21
22 public void setName(String name) {
23 this.name = name;
24 }
25
26 public String getTitle() {
27 return title;
28 }
29
30 public void setTitle(String title) {
31 this.title = title;
32 }
33
34 public void printString(String name, String title) {
35 System.out.println("name = " + name + "title = " + title);
36 }
37
38 public void printString() {
39 System.out.println("name = " + name + " title = " + title);
40 }
41
42 }
其实一个类说的详细点主要是由以下几个部分组成:Class = Field + Constructor + Method (这里说主要由这几个组成,其实还可以有注解Annotation之类生僻的概念,不做讨论了)
Field 就是常说的 属性+属性值,这里其实可以这样理解,属性主要是针对类的,属性值主要是针对对象的。为了方便解释反射,直接在类中定义了默认初始值,让类也具备了属性值。
Constructor 包括了有参构造和无参构造...这些构造方法。
Method就是那些有参,无参,又返回,无返回的各类方法。
一般,我们直接利用类new一个对象出来,现在我们用反射,看怎么新建一个对象
1 // 通过类名称实例化类
2 @Test
3 @Ignore
4 public void testNewClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
5 //方式1
6 // Class clazz = ReflectApp.class; //获得类的字节码
7 // ReflectApp app = (ReflectApp) clazz.newInstance();
8
9 //方式2 类名称所在的路径
10 String className = "springBootExample.example.application.ReflectApp";
11 ReflectApp app = (ReflectApp) Class.forName(className).newInstance();
12
13 app.setName("hu");
14 app.setTitle("hoojjack");
15 app.printString();
16
17 /**
18 * 以上是通过类名获取,下面将通过实例重新获取类名,这正是反射的强大之处
19 *
20 */
21 Class<? extends ReflectApp> instance = app.getClass(); // 获得类的字节码,通过构造方法实例化一个类对象
22 Constructor<? extends ReflectApp> con = instance.getDeclaredConstructor(String.class,String.class);
23 ReflectApp app2 = con.newInstance("hoojjack","hu");
24 app2.printString();
25 }
利用反射获取实例化对象的属性以及属性值:
1 @Test
2 public void testReflectField () throws InstantiationException, IllegalAccessException {
3 Class clazz = ReflectApp.class;
4 Field [] fields =clazz.getDeclaredFields(); //可以获得所有属性
5 // 实例化一个对象,并对属性赋值,以便后面获得对象属性时能得到值
6 ReflectApp app = (ReflectApp) clazz.newInstance();
7 app.setName("hujianjie");
8 app.setTitle("hoojjack");
9 // Field [] fields =clazz.getFields(); //仅获取被声明的public属性
10 for (Field field : fields) {
11 System.out.print(field.getName());
12 //如果是私有属性,必须设置访问权限才可以访问
13 if(!field.isAccessible()) { //对所有的属性来说isAccessible初始都是false,此处可以不用判断
14 field.setAccessible(true); //属性是私有的时候,必须设置为true才能访问
15 System.out.println(" field value : "+field.get(app));
16 }
17 }
18 }
利用反射获取实例化对象的方法:
@Test
public void testReflectMethod () throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class clazz = ReflectApp.class;
Method [] methods = clazz.getDeclaredMethods();
ReflectApp app = (ReflectApp) clazz.newInstance();
app.setName("hujianjie");
app.setTitle("hoojjack");
// 反射调用实例化对象的方法
for (Method method : methods) {
if(method.getParameterCount()>=2) {
method.invoke(app, "hu","jack");
}else if (method.getParameterCount() == 0){
method.invoke(app);
}
}
}
输出结果:
name = hutitle = jack
name = hujianjie title = hoojjack