Java反射

来源:互联网 发布:北京网络预约挂号平台 编辑:程序博客网 时间:2024/05/25 16:39

一、基本介绍

Java反射机制可以的运行期(Runtime)获得任何一个类的字节码。包括接口、变量、方法等信息。还可以让我们在运行期实例化对象,通过调用get/set方法获取变量的值。
1. Java反射包名为:java.lang.reflect 。以下为常用的接口和类
接口
- Type 是 Java 编程语言中所有类型的公共高级接口。
- ParameterizedType 表示参数化类型,即形参类型,如 Collection。

- Field 提供有关类或接口的单个字段(变量)的信息,以及对它的动态访问权限。
- Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
- Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
- Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
2. 反射体系中还有一个重要的类java.lang.Class,它是反射的起点,通过Class对象,才能获取反射体系中其它对象,一共有三种实例化方法,下面API有介绍。
解释:Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

二、常用API介绍

以Father和Son两个类为测试对象,类和测试代码在:
(https://github.com/shengpli/learnExample/tree/master/src/main/java/reflection)
1. 获取类的class对象

Class<Father> fatherClass ;Class<Son> sonClass;//方式一fatherClass = Father.class;sonClass = Son.class;//方式二Father father = new Father();Son son = new Son();fatherClass = (Class<Father>) father.getClass();sonClass = (Class<Son>) son.getClass();//方式三fatherClass = (Class<Father>) Class.forName("reflection.Father");sonClass = (Class<Son>) Class.forName("reflection.Son");

2. 获取变量

  • 获取公有(public)变量
        //getFields只能获取公有的变量        Field[] fields = fatherClass.getFields();        for (Field field : fields) {            System.out.println(field.getName());        }
  • 获取所有变量,并访问私有变量
        //getDeclaredFields能获取所有变量        Field[] declaredFields = fatherClass.getDeclaredFields();        Father father = new Father();        father.setAge("33").setName("zhangsan").setSex("man");        for (Field declaredField : declaredFields) {            //通过调用 setAccessible(true)方法会关闭指定类 Field 实例的反射访问检查,这行代码执行之后不论是私有的、            // 受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。            declaredField.setAccessible(true);            //获取变量名称            System.out.println(declaredField.getName());            //获取变量值            System.out.println(declaredField.get(father));        }

3.获取构造方法,并利用构造方法类实例化对象

        //获取公有的(Public)构造方法类        Constructor<?>[] constructors = sonClass.getConstructors();        //获取所有构造方法类        Constructor<?>[] declaredConstructors = sonClass.getDeclaredConstructors();        //如果你知道你要访问的构造方法的方法参数类型,你可以用下面的方法获取指定的构造方法类        Constructor<Son> sonConstructor = sonClass.getConstructor(new Class[]{String.class, String.class, String.class});        //利用Constructor.newInstance实例化一个类        Son son = sonConstructor.newInstance("zhangsan", "man", "12");        System.out.println(son.toString());        //获取构造方法的参数类        Class<?>[] parameterTypes = sonConstructor.getParameterTypes();        for (Class<?> parameterType : parameterTypes) {            String name = parameterType.getName();            System.out.println(name);        }

4.获取所有public方法;invoke调用方法

        //获取公有的(public)方法类。        Method[] methods = fatherClass.getMethods();        for (Method method : methods) {            System.out.println(method.getName());        }        //通过方法名和参数类型来获取指定的方法。如果你想要获取的方法没有参数,那么在调用 getMethod()方法时第二个参数传入 null 即可        Method singMethod = fatherClass.getMethod("sing", String.class);        System.out.println(singMethod.getName());        //调用方法        Object o = singMethod.invoke(new Father(), "小苹果");        System.out.println(o.toString());

5.获取所有方法

       //获取所有方法        Method[] declaredMethods = fatherClass.getDeclaredMethods();        for (Method declaredMethod : declaredMethods) {            System.out.println(declaredMethod.getName());        }        //获取指定方法        Method play = fatherClass.getDeclaredMethod("play", String.class);        //通过调用 setAccessible()方法会关闭指定类的 Method 实例的反射访问检查,        // 这行代码执行之后不论是私有的、受保护的以及包访问的作用域,你都可以在任何地方访问,即使你不在他的访问权限作用域之内。        play.setAccessible(true);        Father father = new Father();        //调用方法        Object o = play.invoke(father, "ping pong");        System.out.println(o.toString());

6.获取一个类的修饰符(public、private等)

        int modifiers = fatherClass.getModifiers();        System.out.println(Modifier.isPublic(modifiers));

7.获取类的名称

        //全限定类名(包含包名)        String name = fatherClass.getName();        System.out.println(name);        //类的名字(不包含包名)        String simpleName = fatherClass.getSimpleName();        System.out.println(simpleName);

8.获取父类

        Class<? super Son> superclass = sonClass.getSuperclass();        String superclassName = superclass.getName();        System.out.println(superclassName);

9.获取实现接口

        Class<?>[] interfaces = sonClass.getInterfaces();        for (Class<?> anInterface : interfaces) {            String name = anInterface.getName();            System.out.println(name);        }

10.处理泛型变量

        Method eatMethod = fatherClass.getMethod("eat", Map.class);        //获取方法返回参数泛型类型        Type returnType = eatMethod.getGenericReturnType();        if(returnType instanceof ParameterizedType){            ParameterizedType type = (ParameterizedType) returnType;            Type[] returnArguments = type.getActualTypeArguments();            for(Type returnArgument : returnArguments){                Class returnArgClass = (Class) returnArgument;                System.out.println("returnArgClass = " + returnArgClass);            }        }        //获取方法形参泛型类型        Type[] genericParameterTypes = eatMethod.getGenericParameterTypes();        for(Type genericParameterType : genericParameterTypes){            if(genericParameterType instanceof ParameterizedType){                ParameterizedType aType = (ParameterizedType) genericParameterType;                Type[] parameterArgTypes = aType.getActualTypeArguments();                for(Type parameterArgType : parameterArgTypes){                    Class parameterArgClass = (Class) parameterArgType;                    System.out.println("parameterArgClass = " + parameterArgClass);                }            }        }        //获取变量泛型类型        Field field = fatherClass.getField("list");        Type genericType = field.getGenericType();        if(genericType instanceof ParameterizedType){            ParameterizedType fieldType = (ParameterizedType) genericType;            Type[] fieldTypeActualTypeArguments = fieldType.getActualTypeArguments();            for(Type type : fieldTypeActualTypeArguments){                Class fieldArgumentsClass = (Class) type;                System.out.println("fieldArgumentsClass = " + fieldArgumentsClass);            }        }