框架设计的灵魂

反射的概述

  • JAVA反射机制是在运行状态中,对于任意类,都能获取这个类的所有属性和方法;对于任意对象,都能够调用其方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。

通俗的讲:

  • 编写的都是.java -->(jvm) 编译成 .class , 反射就是在 .class 文件里下手
  • 任意类的所有信息在反射面前都是裸体,一般好的框架封装都用到了反射(spring mybatis)

如何用反射获取 .class 文件

  • 获取 .class文件的三种方式
    • getClass
    • 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
    • 通过Class类的静态方法:forName(String className)(超级常用)
		/*------------第一种方式来获取 .class 文件------------*/
        Student student = new Student();
        Class c = student.getClass();
        System.out.println(c);

        /*------------第二种方式来获取 .class 文件------------*/
        Class c2 = String.class;
        System.out.println(c2);

        /*------------第三种方式来获取 .class 文件------------*/
        //这个参数传递的是你当前 .java 文件完整的包名加上类名
        //第三种方式是最常用的,一定要掌握
        try {
            Class c3 = Class .forName("com.offcn.entity.Student");
            System.out.println(c3);
            } catch (Exception e) {
                e.printStackTrace();
            }

注意:

  • 三种方式最常用的是第三种
    a. 第一种 - 对象都有了还要反射干什么。
    b. 第二种 - 需要导入类的包,依赖太强,不导包就抛编译错误。
    c. 第三种 - 一个字符串可以传入也可写在配置文件中等多种方法。

反射获取Student类 有参、无参构造(公有、私有)

	try {
            Class c3 = Class .forName("com.offcn.entity.Student");
            //得到这个对象,实例化对象肯定会走构造方法
            /*------获取所有共有构造方法,返回的参数是构造的数组------*/
            Constructor[] constructors = c3.getConstructors();
            for (int i=0;i<constructors.length;i++){
                System.out.println(i);
            }

            /*------获取所有的构造方法(包括共有与私有构造),返回的参数是构造的数组------*/
            Constructor[] declaredConstructors = c3.getDeclaredConstructors();
            for (int i=0;i<declaredConstructors.length;i++){
                System.out.println(declaredConstructors[i]);
            }

            //实例化对象,如果当前构造是无参的构造,默认一般情况会给一个null
            Constructor studentC = null;
            Object obj = null;

            studentC = c3.getConstructor(int.class); 有参
            studentC = c3.getConstructor(null); 无参

            //这一句话就相当于  Student stu = new Student();

            obj = studentC.newInstance(1); 有参
            obj = studentC.newInstance(null); 无参

            /*-----------获取私有的构造方法-----------*/
            Constructor constructor = c3.getDeclaredConstructor(String.class);
            //通过暴力反射去除私有(通过反射获取所有的私有都要加上这句话)
            constructor.setAccessible(true);
            obj = constructor.newInstance("1");


            Student student1 = (Student) obj;
            student1.print();
           } catch (Exception e) {
                e.printStackTrace();
           }

获取类中公有、私有属性以及怎么给私有属性赋值

			/*---------获取student类里面公有的属性---------*/
            Field[] f = c3.getFields();
            for (int i=0;i<f.length;i++){
                    System.out.println(f[i]);
            }

            /*--------获取所有(包括公有与私有)的属性---------*/
            Field[] f2 = c3.getDeclaredFields();
                for (int i=0;i<f2.length;i++){
                    System.out.println(f2[i]);
            }

            /*---------给私有的属性赋值---------*/
            Field f3 = c3.getDeclaredField("sname");
            f3.setAccessible(true);
            //给其赋值, 第一个参数代表的是你要赋值的对象,第二个参数是你要赋值的具体值
            Object object = c3.getConstructor().newInstance(null);
            f3.set(object,"hehe");

            Student student2 = (Student) object;
            System.out.println(student2.getSname());

获取类中公有、私有方法

			/*-----------获取所有公有的方法-----------*/
            //只要看见 native 方法底层代码都是用 c 或 c++ 编写的
            Method[] m = c3.getMethods();
            for (int i = 0; i < m.length; i++) {
                System.out.println(m[i]);
            }


            /*-----------获取所有公有、私有的方法-----------*/
            Method[] dm = c3.getDeclaredMethods();
            for (int i = 0; i < dm.length; i++) {
                System.out.println(dm[i]);
            }

获取类中单个公有、私有方法并调用

			/*-----------获取单个公有的方法,并调用-----------*/
            Method method = c3.getMethod("getInfo");
            //调用这个方法,第一个参数传递是你要调用方法的对象/第二个参数是你调用方法的参数
            method.invoke(c3.getConstructor().newInstance(null),null);

            /*-----------获取单个私有的方法,并调用-----------*/
            Method method1 = c3.getDeclaredMethod("getString", String.class);
            method1.setAccessible(true);

            Object result = method1.invoke(c3.getConstructor().newInstance(null), "hehe");
            System.out.println(result);

用反射来忽略泛型

			/*-----------用反射来忽略泛型-----------*/
            List<String> list = new ArrayList<String>();
            list.add("hello");
            list.add("world");
            list.add("java");

            //获取其 class 文件
            Class classList = list.getClass();
            Method method2 = classList.getMethod("add",Object.class);
            method2.invoke(list,2);

            for (Object o : list) {
                System.out.println(o);
            }

猜你喜欢

转载自blog.csdn.net/weixin_43332168/article/details/82987562