反射与Constructor、Method、Field类的使用

来源:互联网 发布:00后网络晒怀孕照 编辑:程序博客网 时间:2024/04/28 00:58

     

 

 

 

我个人觉得反射的使用其实就是获得某个类的字节码,然后拿着这个类的字节码进行相应的操作。使用反射判断某变量是否为数组或者是否为基本数据类型、得到某个类的成员变量、某个类的方法、构造函数;这都需要先获得类的字节码才能进行下一步的操作。而按功能分反射大体可以分为:得到类的构造函数、类的方法、类的变量。而与之相对应用的类为:Constructor、Method、Field。下面就简单介绍这里给类的简单使用方法。

     1、(Constructor)得到Integer的构造函数
                    //  得到带一个参数的构造函数
                    Constructor con1 = Integer.class.getConstructor(int.class);
                    /*
                     *实例化一个对象,里面传入一个参数int值,这里传入的参数值要跟得到的构造方法里面的参数值一致。除里下面这种写法,还有另一种:
                     *Integer name = (Integer) con1.newInstance(new Integer(12));
                     *
                     */ 
                      Integer name = (Integer) con1.newInstance(12);
                      System.out.println(name);
                      //  得到Integer所以的构造函数
                      Constructor[] con2 = Integer.class.getConstructors();
                      int num = 0;
                      for (Constructor con : con2) {
                              num++;
                      }
                      System.out.println("Integer一个有"+num+"个构造函数");

     2、(Fields)使用反射对Person类的变量进行相应的操作
                     声明一个Person类,在该类里面定义两个整型的x、y变量和String类型的str1、str2变量,并提供get和set方法。在定义一个带2个整型参数的构造函数(x、y),   重写toString方法 ,返回str1、str2。

                   Person p = new Person(9,21);
  
                  //  得到x的值
                  Field fd1 = p.getClass().getField("x");
                  Object x = fd1.get(p);
                  System.out.println("x = "+x);
                  //  得到私有变量y的值
                  Field fd2 = p.getClass().getDeclaredField("y");
                  fd2.setAccessible(true);
                  Object y = fd2.get(p);
                  System.out.println("y = "+y);
 
                  Field[] fd3 = p.getClass().getFields();// 得到所以成员
                  for (Field field : fd3) {
                        if (field.getType() == String.class) {
                                    String oldValue = (String) field.get(p);
                                    // 如果变量为私有的,就改变不了
                                   String value = oldValue.replace('o', 'a');
                                   field.set(p, value);
                        }
                   }
                  System.out.println(p);


       3、(Method) 使用反射向List<Integer>里面添加字符串并删除集合里面某个元素

                  private static void AddString() throws Exception {
                          List<Integer> list = new ArrayList<Integer>();
                          Method me = list.getClass().getDeclaredMethod("add", Object.class);
                          /* invoke()方法是对象身上的方法 */
                          me.invoke(list, "asd");
                          list.add(123);
                          list.add(22);
                          System.out.println("List的元素有:"+list);

                          //方式一 
                          Method mes1 = list.getClass().getMethod("remove", Object.class);
                          Object obj1 = mes1.invoke(list, 123);
                          System.out.println("obj1的值为"+obj1);
                          System.out.println("删除后的List的元素有:"+list);
                          //方式二
                          Method mes2 = list.getClass().getMethod("remove", int.class);
                         Object obj2 = mes2.invoke(list, 1);
                         System.out.println("obj2的值为"+obj2);
                         System.out.println("删除后的List的元素有:"+list);
                 }

           这里要注意的是方式一和方式二的getMethod()方法的第二个参数的类型。这两种方式都可以达到删除list集合里面的元素,但是区别在于invoke()里面传入的第二个参 数  值。方式一:因为getMethod()传入的的Object.class,因为类型不确定,当java编译器运行到mes1.invoke(list, 123)时,java编译器就会运行Object里面的equals()方法,来判断
invoke()第二个参数值(这里是123)是否跟list里面的元素相当,如果相等就执行删除的方法,否则就不执行;方式二:因为getMethod()传入的的int.class,明确指定了类型是
int类型,当java编译器运行到mes1.invoke(list, 1)时,这时java编译器不会在运行Object里面的equals()方法,而是直接运行List里面的remove()方法,为什么是运行remove()方

法,那是因为在getMethod("remove", int.class)第一个参数已经明确指定运行List里面的remove()方法。这时就要注意了,invoke()第二个参数的值就被限定了,该值的范围只 能大于0小于list集合的长度。

             这里随再介绍一个额外的知识点,就是this()和super()为什么放在首行   

            
                     this()和super()都只能在构造函数里面使用,而且不能同时使用。

                     this()是指向本类的构造函数,是访问本类中的其他构造方法,必须放在首行(必须是有效代码第一句)
                     super()是访问父类中的构造方法,必须放在首行(必须是有效代码的第一句)