zoukankan      html  css  js  c++  java
  • java基础-反射

    1.Class类

    任何一个类都是Class的实例对象,但是Class类的构造方法是私有的,必须由jvm创建对象

    1.1 获取Class类的对象

    (1) 任何一个类都有一个隐含的静态成员变量

    Class clazz = Foo.class;
    

    (2) 通过已知该类的对象通过getclass()方法

    Class c2 = foo.getClass();

    以上的c1,c2为Foo类的类类型

    也就是说万事万物都是对象,类也是对象,是Class类的实例对象,这个对象我们称为该类的类类型,一个类就是Class的一个实例对象

    (3) 

    Class c3 = Class.forName("com.freeht.Foo");

    我们可以通过类的类类型创建该类的对象实例,可以通过c1,c2,c3创建Foo的实例对象

    Foo foo1 = (Foo) c2.newInstance();
    

    2.静态加载和动态加载

    静态加载

    new创建的对象是静态加载类,在编译时刻就需要加载全部可能用到的类

    动态加载

    在运行时加载的类,通过Class.forName(...)来动态加载

    上面的强制类型转换如果想要使用动态加载,那么需要写一个接口,并且强制类型转换成的类需要实现那个接口

    3.基本数据类型都存在类类型

    4.Class类的基本api

    4.1 获取方法的信息

    public class ClassUtil {
    
        /**
         * 打印类的信息,包括类的成员变量和信息
         * @param o 该对象所属类的信息
         */
        public static void printClassMessage(Object o) {
            //要获取类的信息,首先要获取类的类类型
            Class c = o.getClass();     //传递的是哪个子类的对象,c就是该子类的类类型
            //获取类的名称
            System.out.println("类的名称是:" + c.getName());
            //获取类的方法
            //getMethods方法获取的是所有public的函数,包括从父类继承而来的方法
            //getDeclaredMethods获取的是自己声明的方法
            Method[] methods = c.getMethods();  //c.getDeclaredMethods()
            for(int i = 0; i < methods.length; i++) {
                //得到方法的名称
                System.out.println(methods[i].getName());
                //等到返回值类型
                Class retureType = methods[i].getReturnType();
                System.out.println(retureType);
                System.out.println(methods[i].getName());
                //获取参数类型
                Class[] paramsTypes = methods[i].getParameterTypes();
                for(Class clazz : paramsTypes){
                    System.out.println(clazz);
                }
            }
        }
    }
    

    4.2 获取成员变量的信息

    public static void printFieldMessage(Object o) {
              Class c = o.getClass();
             /**
             * 成员变量也是对象
             * java.lang.reflect.Field
             * Field类封装了关于成员变量的信息
             * getFields()方法获取的是所有public的成员变量的信息
             * getDeclaredFields()方法获取的是自己声明的成员变量的信息
             */
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                //得到成员变量的类型的类类型
                Class fieldType = field.getClass();
                String typeName = field.getName();      //得到成员变量的名字
                String fileName = fieldType.getName();  //得到成员变量的类型
                System.out.println(typeName + fileName);
            }
    }
    

    4.3 打印构造函数的信息

        /**
         * 获取构造函数信息
         * 构造函数也是对象
         * @param o
         */
        public static void printConMessage(Object o) {
            Class c = o.getClass();
            Constructor[] constructors = c.getConstructors();       //c.getDeclaredConstructors()
            for(Constructor constructor : constructors) {
                Class[] classes = constructor.getParameterTypes();      //得到构造函数的类类型
                for (Class c1 : classes) {
                    System.out.println(c1.getName());
                }
            }
        }
    

      

    5.方法的反射

    方法的名称和方法的参数列表才能决定某个列表

    5.1 方法反射的操作

    method.invoke(对象,参数列表)

    public class MethodDemo1 {
        public static void main(String[] args) {
            //要获取print(int a, int b)
            //1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
            A a1 = new A();
            Class c1 = a1.getClass();
            /**
             * getMethod() 获得的是public的方法
             */
            try {
                //Method method = c1.getMethod("print", new Class[]{int.class, int.class});
                Method method = c1.getMethod("print", int.class, int.class);
                //方法的反射操作
                //是指method对象来进行方法调用,和a1.print()的调用相同
                //方法如果没有返回类型,那么就是null,如果有返回值类型,那么就是具体的返回值类型
                Object o = method.invoke(a1, new Object[]{10,20});
                Method method1 = c1.getMethod("print", String.class, String.class);
                Object o1 = method1.invoke(a1, "hello", "world");
    
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
    
    class A{
        public void print(int a, int b) {
            System.out.println(a + b);
        }
    
        public void print(String a, String b) {
            System.out.println(a.toUpperCase() + b.toUpperCase());
        }
    }
    

      

    6.泛型的本质

    反射的操作都是编译之后的操作

    编译之后的集合是去泛型化的,也就是说java中集合泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效了

    public class MethonDemo2 {
        public static void main(String[] args) {
            List list = new ArrayList();
            List<String> list1 = new ArrayList<String>();
            list1.add("hello");
            Class c1 = list.getClass();
            Class c2 = list1.getClass();
            System.out.println(c1 == c2);
            try {
                Method method = c1.getMethod("add", Object.class);
                method.invoke(list1, 100);  //绕过了编译就绕过了泛型
                System.out.println(list1.size());
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 相关阅读:
    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)K Co-prime Permutation
    2020 CCPC绵阳站赛后回忆+总结
    CF 1473D Program
    Educational Codeforces Round 100 (Rated for Div. 2) 补题情况
    Codeforces Round #690 (Div. 3) (补题情况)
    这个博客停用,新博客地址:www.baccano.fun
    炫酷路径(牛客)
    洛谷 P1123 取数游戏
    洛谷P2802 回家
    cf上分的失落->高兴->更失落
  • 原文地址:https://www.cnblogs.com/freeht/p/12687676.html
Copyright © 2011-2022 走看看