Java 反射机制

设计模式中,有很多地方会用到反射机制,下面通过代码来讲解反射机制。

一个实体类如下:

 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
原文地址:https://www.cnblogs.com/hoojjack/p/8490318.html