美文网首页
10、反射

10、反射

作者: 浮生若梦OvO | 来源:发表于2019-06-21 10:21 被阅读0次

    一、 反射格式:

               修饰符 返回值类型 方法名(数据类型... 变量)'
    
               {
                        函数体;
               }
    

    注意:这里的变量其本质是一个数组。如果你写程序的时候,想用可变参数,最好把可变参数定义在末尾。

    二、反射方法

           //public Constructor<?>[] getConstructors()
            Constructor[] cons = c.getConstructors();
            //  所有构造方法
    
           //public Constructor<?>[] getDeclaredConstructors()
           Constructor[] cons = c.getDeclaredConstructors();
              Class c = Class.forName("cn.itcast_01.Person");
    
              // 创建对象
              Constructor con = c.getConstructor();
              Object obj = con.newInstance();
    
               Method[] methods = c.getMethods();// 所有公共方法,包括父类的
               Method[] methods = c.getDeclaredMethods();// 本类的所有方法
             
              //第一种:无参数无返回值
              Method m1 = c.getMethod("show", null);
              m1.invoke(obj, null);
              System.out.println("---------------");
              //第二种:带参数无返回值
              Method m2 = c.getMethod("function", String.class);
              m2.invoke(obj, "林青霞");
              System.out.println("---------------");
              //第三种:带多个参数有返回值
              Method m3 = c.getMethod("reutrnValue", String.class,int.class);
              Object ooo = m3.invoke(obj, "林青霞",26);
              System.out.println(ooo);
              System.out.println("---------------");
              //第四种:私有方法的调用
              Method m4 = c.getDeclaredMethod("hello", null);
              m4.setAccessible(true);
              m4.invoke(obj, null)
    

    三、反射概述和获取字节码文件的方式

    • 可变参数:
    JDK5新特性举例:
    public static void main(String[] args) {
              //我也不知道别人要传递几个参数。
              // 只有在别人调用的时候,别人才明确。
              int a = 10;
              int b = 20;
              int result = sum(a, b);
              System.out.println(result);
              int c = 30;
              result = sum(a, b, c);
              System.out.println(result)
              int d = 40;
              result = sum(a, b, c, d);
              System.out.println(result);
    
              int e = 50;
              result = sum(a, b, c, d, e);
              System.out.println(result);
    
    //将参数定义为可变参数,
         public static int sum(int... x) {
              int result = 0;
              for (int i : x) {
                   result += i;
              }
              return result;     }
    
    • 概念
      反射:在运行状态下,通过class文件对象(Class的对象),去使用构造方法,成员变量,成员方法
    • 获取到class文件对象(字节码文件对象)
      a:Object类的getClass()方法。
      Class c = 对象.getClass();
      b:数据类型的静态的class属性
      Class c =类名.class;
      c:通过Class类的静态方法forName(String className)
      Class c = Class.forName("cn.itcast_01.Person")(包名.类名)

    四、通过反射获取构造方法并使用

    • 获取字节码文件对像
      Class c=Class.forName( "cn.itcasn_01.Person");
    • 获取构造器对象
      a 所有公共构造方法
      b 获取无参构造方法
         Constructor con = c.getConstructor( );// 表示我使用的是无参数构造方法
          通过构造器对象创建对象
        // public T newInstance(Object... initargs);
         Object obj = con.newInstance();
    

    c 获取有参构造方法

        //public Constructor<T> getConstructor(Class<?>... parameterTypes)
              Class[] classes = new Class[2];
              classes[0] = String.class;
              classes[1] = int.class;
            Constructor con = c.getConstructor(classes);
            //  改进版
              Constructor con = c.getConstructor(new Class[] { String.class, int.class });
             //最终版
             Constructor con = c.getConstructor(String.class, int.class);
             // 创建对象
             public T newInstance(Object... initargs)
             Object obj = con.newInstance("林青霞", 26);
    

    五、通过反射获取成员变量并使用

    • 获取成员变量并使用
              // 获取字节码文件对象
              Class c = Class.forName("cn.itcast_01.Person");
    
              // 获取成员变量对象
               Field[] fields = c.getFields();// 获取所有公共的成员变量
               Field[] fields = c.getDeclaredFields();// 获取所有的成员变量
             
              //获取构造器对象
              Constructor con = c.getConstructor();
              Object obj = con.newInstance();
    
              // 获取单个的成员变量
              Field field = c.getField("age");
             
              // obj.field = 20;
              //public void set(Object obj,Object value)
              field.set(obj, 20);//给obj对象的field字段赋值为20
    
    • 获取私有成员变量并使用
            // 获取字节码文件对象
              Class c = Class.forName("cn.itcast_01.Person");
    
              // 创建对象
              Constructor con = c.getConstructor();
              Object obj = con.newInstance();
    
              // 获取年龄并赋值
              Field ageField = c.getField("age");
              ageField.set(obj, 26);
    
              // 获取姓名并赋值
              // NoSuchFieldException
              // Field nameField = c.getField("name");
              Field nameField = c.getDeclaredField("name");
            
              //public void setAccessible(boolean flag)
              //在访问私有成员变量时,暴力访问,不然会出现  IllegalAccessException  错误
              nameField.setAccessible(true);//你就不要限制我了。
              nameField.set(obj, "林青霞");
    

    六、面试题

    在ArrayList<Integer>的集合中添加一个String类型的对象,如何实现呢?

    *通过反射实现
    * 反射可以越过泛型检查。
    public class ArrayListTest {
         public static void main(String[] args) throws Exception {
              ArrayList<Integer> array = new ArrayList<Integer>();
               array.add(10);
       
              // 获取字节码文件对象
              Class c = array.getClass();
              Method m = c.getMethod("add", Object.class);
              m.invoke(array, "hello");
              m.invoke(array, "world");
              m.invoke(array, "java");
    
              System.out.println(array);
         }
    }
    

    相关文章

      网友评论

          本文标题:10、反射

          本文链接:https://www.haomeiwen.com/subject/puwjqctx.html