zoukankan      html  css  js  c++  java
  • Java反射

    Java 反射是可以让我们在运行时获取类的函数、属性、父类、接口等 Class 内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用.

    当我们编写完一个 Java 项目之后,所有的 Java 文件都会被编译成一个.class 文件,这些 Class 对象承载了这个类型的父类、接口、构造函数、方法、属性等原始信息,这些 class 文件在程序运行时会被 ClassLoader 加载到虚拟机中。当一个类被加载以后,Java 虚拟机就

    会在内存中自动产生一个 Class 对象。我们通过 new 的形式创建对象实际上就是通过这些 Class 来创建,只是这个过程对于我们是不透明的而已。

    1.如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class 对象。

    Class<?> myObjectClass = MyObject.class;

    2.如果你已经得到了某个对象,但是你想获取这个对象的 Class 对象,那么你可以通过下面的方法得到:

    Student me = new Student("mr.simple");
    Class<?> clazz = me.getClass();

    3.如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class 对象:

    Class<?> myObjectClass = Class.forName("com.simple.User");

    接口说明
    // 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student". ( 常用方式 )
    public static Class<?> forName (String className)
    
    // 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student";
    // 参数 2 为是否要初始化该 Class 对象,参数 3 为指定加载该类的 ClassLoader.
    public static Class<?> forName (String className, boolean shouldInitialize, ClassLoader classLoader)

    通过 Class 对象构造目标类型的对象:

       private static void classForName() {
            try {
                // 获取 Class 对象
                Class<?> clz = Class.forName("org.java.advance.reflect.Student");
                // 通过 Class 对象获取 Constructor,Student 的构造函数有一个字符串参数
                // 因此这里需要传递参数的类型 ( Student 类见后面的代码 )
                Constructor<?> constructor = clz.getConstructor(String.class);
                // 通过 Constructor 来创建 Student 对象
                Object obj = constructor.newInstance("mr.simple");
                System.out.println(" obj :  " + obj.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    接口说明
     // 获取一个公有的构造函数,参数为可变参数,如果构造函数有参数,那么需要将参数的类型传递给 getConstructor 方法
     public Constructor<T> getConstructor (Class...<?> parameterTypes)
    // 获取目标类所有的公有构造函数 public Constructor[]<?> getConstructors ()

         私有方法调用必须设置accessible为true,不进行java语言访问检查

     Constructor<?> constructor = clz.getConstructor(String.class);
     // 设置 Constructor 的 Accessible
     constructor.setAccessible(true);
    
     // 设置 Methohd 的 Accessible
     Method learnMethod = Student.class.getMethod("learn", String.class);
     learnMethod.setAccessible(true);

    获取方法:
    要获取当前类中定义的所有方法可以通过 Class 中的 getDeclaredMethods 函数,它会获取到当前类中的 public、default、protected、private 的所有方法。
    而 getDeclaredMethod(String name, Class...<?> parameterTypes)则是获取某个指定的方法

    要获取当前类以及父类中的所有 public 方法可以通过 Class 中的 getMethods 函数,而 getMethod 则是获取某个指定的方法

       接口说明

    // 获取 Class 对象中指定函数名和参数的函数,参数一为函数名,参数 2 为参数类型列表
    public Method getDeclaredMethod (String name, Class...<?> parameterTypes)
    
    // 获取该 Class 对象中的所有函数( 不包含从父类继承的函数 )
    public Method[] getDeclaredMethods ()
    
    // 获取指定的 Class 对象中的**公有**函数,参数一为函数名,参数 2 为参数类型列表
    public Method getMethod (String name, Class...<?> parameterTypes)
    
    // 获取该 Class 对象中的所有**公有**函数 ( 包含从父类和接口类集成下来的函数 )
    public Method[] getMethods ()
    这里需要注意的是 getDeclaredMethod 和 getDeclaredMethods 包含 private、protected、default、public 的函数,并且通过这两个函数获取到的只是在自身中定义的函数,从父类中集成的函数不能够获取到。
    而 getMethod 和 getMethods 只包含 public 函数,父类中的公有函数也能够获取到。


    获取属性:
    要获取当前类中定义的所有属性可以通过 Class 中的 getDeclaredFields 函数,它会获取到当前类中的 public、default、protected、private 的所有属性。
    而 getDeclaredField 则是获取某个指定的属性

    要获取当前类以及父类中的所有 public 属性可以通过 Class 中的 getFields 函数,而 getField 则是获取某个指定的属性。

        接口说明

    // 获取 Class 对象中指定属性名的属性,参数一为属性名
    public Method getDeclaredField (String name)
    
    // 获取该 Class 对象中的所有属性( 不包含从父类继承的属性 )
    public Method[] getDeclaredFields ()
    
    // 获取指定的 Class 对象中的**公有**属性,参数一为属性名
    public Method getField (String name)
    
    // 获取该 Class 对象中的所有**公有**属性 ( 包含从父类和接口类集成下来的公有属性 )
    public Method[] getFields ()
    这里需要注意的是 getDeclaredField 和 getDeclaredFields 包含 private、protected、default、public 的属性,并且通过这两个函数获取到的只是在自身中定义的属性,从父类中集成的属性不能够获取到。
    而 getField 和 getFields 只包含 public 属性,父类中的公有属性也能够获取到。

    获取 Class 对象的父类:
     Student student = new Student("mr.simple");
        Class<?> superClass = student.getClass().getSuperclass();
        while (superClass != null) {
            System.out.println("Student's super class is : " + superClass.getName());
            // 再获取父类的上一层父类,直到最后的 Object 类,Object 的父类为 null
            superClass = superClass.getSuperclass();
        }

       获取 Class 对象中实现的接口:

     private static void showInterfaces() {
            Student student = new Student("mr.simple");
            Class<?>[] interfaceses = student.getClass().getInterfaces();
            for (Class<?> class1 : interfaceses) {
                System.out.println("Student's interface is : " + class1.getName());
            }
        }

     

      获取注解:

    通过反射 api 我们也能够获取一个 Class 对象获取类型、属性、函数等相关的对象,通过这些对象的 getAnnotation 接口获取到对应的注解信息。

    @Test(tag = "Student class Test Annoatation")
    public class Student extends Person implements Examination {
        // 年级
        @Test(tag = "mGrade Test Annotation ")
        int mGrade;
    
        // ......
    }

    然后通过相关的注解函数得到注解信息

    private static void getAnnotationInfos() {
            Student student = new Student("mr.simple");
            Test classTest = student.getClass().getAnnotation(Test.class);
            System.out.println("class Annotatation tag = " + classTest.tag());
    
            Field field = null;
            try {
                field = student.getClass().getDeclaredField("mGrade");
                Test testAnnotation = field.getAnnotation(Test.class);
                System.out.println("属性的 Test 注解 tag : " + testAnnotation.tag());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

       接口说明

    // 获取指定类型的注解
    public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
    // 获取 Class 对象中的所有注解 public Annotation[] getAnnotations();
     
  • 相关阅读:
    Oracle求连续的年份
    关于Extjs MVC模式上传文件的简单方式
    后进先出 stack、 先进先出Queue
    python的文件操作
    C#的接口
    C#的访问级别
    C#的继承
    SQL查询语句 常用示例
    SQL Server数据库常用函数
    数据库建立和连接
  • 原文地址:https://www.cnblogs.com/krislight1105/p/9999657.html
Copyright © 2011-2022 走看看