首页 > 编程语言 > 详细

13.Java的反射

时间:2020-01-21 23:56:25      阅读:165      评论:0      收藏:0      [点我收藏+]

一.Java反射

1.概念:反射是框架设计的灵魂

  • 框架:半成品软件。可以在框架的基础上进行软件开发,简化代码。
  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制。
    • 可以在程序运行过程中操作这些对象。
    • 可以解耦提高程序的可扩展行。

2.Java代码在计算机中经历的三个阶段:

  • Source源代码阶段
  • Class类对象阶段
  • Runtime运行时阶段

技术分享图片

3.获取class对象的三种方式:

  • Class.forName("全类名"):将字节码文件加载进内存返回class对象。对应Java代码的Source源代码阶段。
    • 用于配置文件:将类名定义在配置文件中,读取配置文件加载类。
  • 类名.class:通过类名的属性class获取。对应Java代码的Class类对象阶段。
    • 用于参数传递。
  • 对象.getClass():getClass()方法在Object类中定义。对应Java代码的Runtime阶段。
    • 用于对象的获取字节码的方式。
  • 结论:对于同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的Class对象都是同一个。

Person类:

 1 public class Person {
 2 
 3     private String name;
 4     private int age;
 5 
 6     public String a;
 7 
 8     public Person() {
 9     }
10 
11     private Person(String name) {
12         this.name = name;
13     }
14 
15     public Person(String name, int age) {
16         this.name = name;
17         this.age = age;
18     }
19 
20     public Person(String name, int age, String a) {
21         this.name = name;
22         this.age = age;
23         this.a = a;
24     }
25 
26 
27     public String getName() {
28         return name;
29     }
30 
31     public void setName(String name) {
32         this.name = name;
33     }
34 
35     public int getAge() {
36         return age;
37     }
38 
39     public void setAge(int age) {
40         this.age = age;
41     }
42 
43     @Override
44     public String toString() {
45         return "Person{" +
46                 "name=‘" + name + ‘\‘‘ +
47                 ", age=" + age +
48                 ", a=‘" + a + ‘\‘‘ +
49                 ‘}‘;
50     }
51 
52     public void publicMethod1() {
53         System.out.println("publicMethod1");
54     }
55 
56     public void publicMethod2(String s) {
57         System.out.println("publicMethod2:参数为" + s);
58     }
59 
60     private void privateMethod1() {
61         System.out.println("privateMethod1");
62     }
63 
64     private void privateMethod2(String s) {
65         System.out.println("privateMethod2:参数为" + s);
66     }
67 }

主函数:

 1 public class ReflectDemo1 {
 2 
 3     public static void main(String[] args) throws ClassNotFoundException {
 4 
 5         //1.Class.forName("全类名")
 6         Class cls1 = Class.forName("day08.Person");
 7         System.out.println(cls1);
 8 
 9         //2.类名.class
10         Class cls2 = Person.class;
11         System.out.println(cls2);
12 
13         //3.对象.getClass()
14         Person p = new Person();
15         Class cls3 = p.getClass();
16         System.out.println(cls3);
17 
18 
19         //比较三个对象是否为同一对象
20         System.out.println(cls1 == cls2);
21         System.out.println(cls1 == cls3);
22     }
23 }

结果:

1 class day08.Person
2 class day08.Person
3 class day08.Person
4 true
5 true

4.Class对象功能

  • 获取功能:
    1. 获取成员变量们:Field类
      • Field[] getFields():获取所有public修饰的成员变量
      • Field getField(String name):利用成员变量名获取public的成员变量
      • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
      • Field getDeclaredField(String name):利用成员变量名获取任意的成员变量
    2. 获取构造函数们:Constructor类
      • Constructor<?>[] getConstructors():获取空参数public构造函数
      • Constructor<T> getConstructor(类<?>...  parameterTypes):根据参数获取到类的public构造函数
      • Constructor<?>[] getDeclaredConstructors():获取空参数任意构造函数
      • Constructor<T> getDeclaredConstructor(类<?>...  parameterTypes):根据参数获取到类的任意构造函数
    3. 获取成员方法们:Method类
      • Method[] getMethods():获取自己以及基类所有public方法
      • Method getMethod(String name,类<?>... parameterTypes):根据参数获得public方法
      • Method[] getDeclaredMethods():获取自己以及基类所有方法
      • Method getDeclaredMethod(String name,类<?>... parameterTypes):根据参数获得任意方法
    4. 获取类名:
      • String getName()
  • Field:成员变量
    • 操作:
      • 设置值:void set(Object obj, Object value)
      • 获取值:get(Object obj)
      • 忽略访问权限修饰符的安全检查(暴力反射):setAccessible(true) 
  • Constructor:构造方法
    • 创建对象:
      • T newInstance(Object... initargs)
      • 如果使用空参数构造方法,则操作可以简化:Class对象的newInstance方法
    • 忽略访问权限修饰符的安全检查(暴力反射):setAccessible(true) 
  • Method:方法对象
    • 执行方法:Object invoke(Object obj, Object... args)
    • 获取方法名:String getName()
    • 忽略访问权限修饰符的安全检查(暴力反射):setAccessible(true)

Field使用:

 1 public class ReflectDemo2 {
 2 
 3     public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
 4 
 5         Class personClass = Person.class;
 6 
 7         //1.getFields:获取所有public修饰的成员变量
 8         System.out.println("1.getFields:获取所有public修饰的成员变量");
 9         Field[] fields = personClass.getFields();
10         for (Field f :fields) {
11             System.out.println(f);
12         }
13         /**输出:
14          * 1.getFields:获取所有public修饰的成员变量
15          * public java.lang.String day08.Person.a
16          */
17 
18         //2.getField:利用成员变量名获取public的成员变量
19         System.out.println("2.getField:利用成员变量名获取public的成员变量");
20         Field a = personClass.getField("a");
21         //获取成员变量值
22         Person p = new Person();
23         Object aValue = a.get(p);
24         System.out.println(aValue);
25         //设置成员变量值
26         a.set(p,"111");
27         System.out.println(p);
28         /**输出:
29          * 2.getField:利用成员变量名获取public的成员变量
30          * null
31          * Person{name=‘null‘, age=0, a=‘111‘}
32          */
33 
34         //3.getDeclaredFields:获取所有的成员变量,不考虑修饰符
35         System.out.println("3.getDeclaredFields:获取所有的成员变量,不考虑修饰符");
36         Field[] declaredFields = personClass.getDeclaredFields();
37         for (Field f :declaredFields) {
38             System.out.println(f);
39         }
40         /**输出:
41          * 3.getDeclaredFields:获取所有的成员变量,不考虑修饰符
42          * private java.lang.String day08.Person.name
43          * private int day08.Person.age
44          * public java.lang.String day08.Person.a
45          */
46 
47         //4.getDeclaredField:利用成员变量名获取任意的成员变量
48         System.out.println("4.getDeclaredField:利用成员变量名获取任意的成员变量");
49         Field name = personClass.getDeclaredField("name");
50         //忽略访问权限修饰符的安全检查
51         name.setAccessible(true);//暴力反射
52         Object nameValue = name.get(p);
53         System.out.println(nameValue);
54         name.set(p,"王");
55         System.out.println(p);
56         /**输出:
57          * 4.getDeclaredField:利用成员变量名获取任意的成员变量
58          * null
59          * Person{name=‘王‘, age=0, a=‘111‘}
60          */
61     }
62 }

Constructor使用:

 1 public class ReflectDemo2 {
 2 
 3     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
 4 
 5         Class personClass = Person.class;
 6 
 7         //1.getConstructor():获取空参数public构造函数
 8         System.out.println("1.getConstructor(Class<?>... parameterTypes):获取空参数public构造函数");
 9         Constructor constructor1 = personClass.getConstructor();
10         System.out.println(constructor1);
11         //创建对象
12         Object person1 = constructor1.newInstance();
13         System.out.println(person1);
14 
15         //简化空参
16         System.out.println("简化空参");
17         Object o = personClass.newInstance();
18         System.out.println(o);
19         /**输出:
20          * 1.getConstructor(Class<?>... parameterTypes):获取空参数构造函数
21          * public day08.Person()
22          * Person{name=‘null‘, age=0, a=‘null‘}
23          * 简化空参
24          * Person{name=‘null‘, age=0, a=‘null‘}
25          */
26 
27         //2.getConstructor(Class<?>... parameterTypes):根据参数获取到类的public构造函数
28         System.out.println("2.getConstructor(Class<?>... parameterTypes):根据参数获取到类的public构造函数");
29         Constructor constructor2 = personClass.getConstructor(String.class, int.class);
30         System.out.println(constructor2);
31         //创建对象
32         Object person2 = constructor2.newInstance("王",23);
33         System.out.println(person2);
34         /**输出:
35          * 2.getConstructor(Class<?>... parameterTypes):根据参数获取到类的构造函数
36          * public day08.Person(java.lang.String,int)
37          * Person{name=‘王‘, age=23, a=‘null‘}
38          */
39 
40         //3.getDeclaredConstructor(Class<?>... parameterTypes):根据参数获取到类的任意构造函数
41         System.out.println("3.getDeclaredConstructor(Class<?>... parameterTypes):根据参数获取到类的任意构造函数");
42         Constructor constructor3 = personClass.getDeclaredConstructor(String.class);
43         //忽略访问权限修饰符的安全检查
44         constructor3.setAccessible(true);//暴力反射
45         System.out.println(constructor3);
46         //创建对象
47         Object person3 = constructor3.newInstance("张");
48         System.out.println(person3);
49         /**输出:
50          * 3.getDeclaredConstructor(Class<?>... parameterTypes):根据参数获取到类的任意构造函数
51          * private day08.Person(java.lang.String)
52          * Person{name=‘张‘, age=0, a=‘null‘}
53          */
54     }
55 }

Method使用:

  1 public class ReflectDemo2 {
  2 
  3     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
  4 
  5         Class personClass = Person.class;
  6 
  7         //1.getMethods:获取自己以及基类所有public方法
  8         System.out.println("1.getMethods:获取自己以及基类所有public方法");
  9         Method[] methods1 = personClass.getMethods();
 10         for (Method m : methods1) {
 11             System.out.println(m);
 12             System.out.println(m.getName());
 13         }
 14         /**输出:
 15          * 1.getMethods:获取自己以及基类所有public方法
 16          * public java.lang.String day08.Person.toString()
 17          * toString
 18          * public java.lang.String day08.Person.getName()
 19          * getName
 20          * public void day08.Person.setName(java.lang.String)
 21          * setName
 22          * public void day08.Person.publicMethod2(java.lang.String)
 23          * publicMethod2
 24          * public void day08.Person.publicMethod1()
 25          * publicMethod1
 26          * public int day08.Person.getAge()
 27          * getAge
 28          * public void day08.Person.setAge(int)
 29          * setAge
 30          * public final void java.lang.Object.wait() throws java.lang.InterruptedException
 31          * wait
 32          * public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
 33          * wait
 34          * public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
 35          * wait
 36          * public boolean java.lang.Object.equals(java.lang.Object)
 37          * equals
 38          * public native int java.lang.Object.hashCode()
 39          * hashCode
 40          * public final native java.lang.Class java.lang.Object.getClass()
 41          * getClass
 42          * public final native void java.lang.Object.notify()
 43          * notify
 44          * public final native void java.lang.Object.notifyAll()
 45          * notifyAll
 46          */
 47 
 48         //2.getMethod(String name, Class<?>... parameterTypes):根据参数获得public方法
 49         System.out.println("2.getMethod(String name, Class<?>... parameterTypes):根据参数获得任意方法");
 50         //无参
 51         Method method2_1 = personClass.getMethod("publicMethod1");
 52         Person p2_1 = new Person();
 53         //执行方法
 54         method2_1.invoke(p2_1);
 55 
 56         //有参
 57         Method method2_2 = personClass.getMethod("publicMethod2", String.class);
 58         Person p2_2 = new Person();
 59         //执行方法
 60         method2_2.invoke(p2_2, "这是有参的public方法");
 61         /**输出:
 62          * 2.getMethod(String name, Class<?>... parameterTypes):根据参数获得public方法
 63          * publicMethod1
 64          * publicMethod2:参数为这是有参的public方法
 65          */
 66 
 67         //3.getDeclaredMethods:获取自己以及基类所有方法
 68         System.out.println("3.getMethods:获取自己以及基类所有方法");
 69         Method[] methods2 = personClass.getDeclaredMethods();
 70         for (Method m : methods2) {
 71             System.out.println(m);
 72             System.out.println(m.getName());
 73         }
 74         /**输出:
 75          * 3.getMethods:获取自己以及基类所有方法
 76          * public java.lang.String day08.Person.toString()
 77          * toString
 78          * public java.lang.String day08.Person.getName()
 79          * getName
 80          * public void day08.Person.setName(java.lang.String)
 81          * setName
 82          * private void day08.Person.privateMethod1()
 83          * privateMethod1
 84          * public void day08.Person.setAge(int)
 85          * setAge
 86          * public void day08.Person.publicMethod1()
 87          * publicMethod1
 88          * private void day08.Person.privateMethod2(java.lang.String)
 89          * privateMethod2
 90          * public void day08.Person.publicMethod2(java.lang.String)
 91          * publicMethod2
 92          * public int day08.Person.getAge()
 93          * getAge
 94          */
 95 
 96         //4.getDeclaredMethod(String name, Class<?>... parameterTypes):根据参数获得任意方法
 97         System.out.println("4.getDeclaredMethod(String name, Class<?>... parameterTypes):根据参数获得public方法");
 98         //无参
 99         Method method4 = personClass.getDeclaredMethod("privateMethod2", String.class);
100         //忽略访问权限修饰符的安全检查
101         method4.setAccessible(true);//暴力反射
102         Person p4 = new Person();
103         //执行方法
104         method4.invoke(p4, "这是有参的private方法");
105         /**输出:
106          * 4.getDeclaredMethod(String name, Class<?>... parameterTypes):根据参数获得public方法
107          * privateMethod2:参数为这是有参的private方法
108          */
109     }
110 }

获取类名:

 1 public class ReflectDemo2 {
 2 
 3     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
 4 
 5         Class personClass = Person.class;
 6 
 7         //获取类名
 8         String className = personClass.getName();
 9         System.out.println(className);
10         /**输出:
11          * day08.Person
12          */
13     }
14 }

5.案例:读取配置文件生成类执行方法

目录配置:

技术分享图片

主程序类:ReflectDemo2

public class ReflectDemo2 {

    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro = new Properties();

        //1.2加载配置文件,转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectDemo2.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("config.properties");
        pro.load(is);

        //2.获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");
        Class parameterType = Class.forName(pro.getProperty("parameterType"));

        //3.加载该类进内存
        Class cls = Class.forName(className);

        //4.创建对象
        Object obj = cls.newInstance();

        //5.获取方法对象
        Method method = cls.getDeclaredMethod(methodName,parameterType);
        method.setAccessible(true);

        //执行方法
        method.invoke(obj,"执行私有方法");
    }
}

配置文件:config.properties

1 className=day08.Person
2 methodName=privateMethod2
3 parameterType=java.lang.String

13.Java的反射

原文:https://www.cnblogs.com/zhihaospace/p/12227325.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!