zoukankan      html  css  js  c++  java
  • Java的反射机制Reflect

    简介:

    动态获取类的信息、动态调用对象的方法的功能叫做:Java 的反射(Reflection)机制。

    Reflection是不同于C++等静态语言,而被视为准动态语言的关键性质。反射机制允许程序在运行时,透过Reflection API取得任何一个已知的class的内部信息,(功能列表)如:

    • 得到类型修饰符public、private等。
    • 得到其父类superclass, 其本身的类class。
    • 实现了哪些interface也可以得到。
    • 获得所有的field和method,并且可以在运行时,改变field的值、调用method,但是不能获得method的定义和实现 —— 即实例化这个类,生成这个类的对象。

    通过反射机制,Java可以加载一个在运行时才获得名称的class,获悉其完整的构造,并生成对象(而这个对象是JVM生成的,即new Instance。相当于通过逆推,从计算机的角度完成了,人学习并使用一个类的功能。而这种能力的术语被称为introspection内省。

    实现Reflect相关的类:

    在JDK中,主要由以下类来实现反射机制获取这些类的对象),这些类(除了第一个)都位于java.lang.reflect包中:

    • Class类:代表一个类(即Class这个类存放Java的类:Class类的一个实例就是我们平常所说的一个类),位于java.lang包中。
    • Field类:代表类的成员变量 / 属性。
    • Method类:代表类的方法。
    • Constructor类:代表类的构造方法。
    • Array类:提供了动态创建数组,以及访问数组元素的静态方法等。

    1、Class类(下面Class对象的概念和一般对象有点混乱):

    Class类是整个反射机制的基础:一个类的所有对象,都对应于这个类,即一个Class对象而已。而实际上所有的类,或者说所有的Class对象都是由JVM生成。所以通过Class类的某些方法(对于Class类或者Class对象来说就是静态方法,对于不是Class对象的、一般的对象就是普通方法),可以获得指定的Class对象,也就是一个类的整个结构。之后就可以通过这个Class对象来操纵相应的类的一般对象。

    Class对象不能通过new的方式创建,如上所说,有两种方法可以获取:

    1. 静态方法:Class clazz = Class.forName("java.lang.String");或者Class clazz = String.class;
    2. 普通方法getClass():String str = "";Class clazz = str.getClass(); —— 类是没有getClass方法的。
    public class TesterMain {
    
        public static void main(String[] args) {
            String pagename = "";
            try {
                //下面三种方法都是获得同一个Class对象:String
                Class c3 = Class.forName("java.lang.String");
                Class c1 = pagename.getClass();
                Class c2 = String.class;
                if(c1.equals(c2) && c1.equals(c3) && c2.equals(c3)) {
                    System.out.println("test1");
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
    }

    2、Field类:

    一个类中的每个属性都对应于一个Field对象。

    import java.lang.reflect.Field;
    import Entity.Test;
    
    public class TesterMain {
    
        public static void main(String[] args) {
            try {
                //Test类:public String testPublic;private String testNonPublic;
                Class clazz = Test.class;
                // 一 :
                Field publicField = clazz.getField("testPublic");//获取指定的public属性
                Field everyWhereField = clazz.getDeclaredField("testNonPublic");//获取指定的任何属性(不论限定符)
                
                System.out.println(publicField + "
    " + everyWhereField);
                System.out.println("
    ");
                //out:public java.lang.String Entity.Test.test
                //private java.lang.String Entity.Test.testNonPublic
                
                // 二 :
                Field[] publicFields = clazz.getFields();//获取Class对象中的所有public Field对象
                for (Field field : publicFields) {
                    System.out.println(field);
                }
                Field[] allFields = clazz.getDeclaredFields();//获取所有的属性(不论限定符)
                for (Field field : allFields) {
                    System.out.println(field);
                }
            } catch (SecurityException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    
    }

    3、Method类(下面把Method对象对应的方法,简称为Method方法):

    先给出示例代码,然后解释:

    String str = "hello";
    try {
        Method method = str.getClass().getMethod("charAt", int.class);//不能用Integer,因为charAt方法接收的是int,而int和Integer的Class对象是不一样的
        char c = (char) method.invoke(str, 1);
        System.out.println(c);
    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        e.printStackTrace();
    }

    通过Class对象,获得Method对象的方式:

    • 按照方法名称 + 参数类型的Class对象列表,获得某个public Method对象(包括从父类或接口继承的方法):Method getMethod(String methodName,Class<?> ... parameterTypes)。
    • 获得所有的public方法(包括继承的方法):Method [] getMethods()。
    • 若不论方法的限定符,对应的有:getDeclaredMethod(String methodName,Class<?> ... parameterType)和 getDeclaredMethods()。

    使用Method对象:

    invoke方法,用于调用Method方法,函数原型为:Object invoke(Object obj,Object ... obj),参数一:原本调用Method方法的对象,参数二:Method方法的实参列表。 —— 因此,若Method方法是static的,则参数一为null。

    4、Constructor类:

    5、Array类:

    最后,通过反射得到了Class对象,那么就可以用Class对象构造出对应的类的实例

    // 一 :默认构造函数:String string1 = new String();
    Class clazz = String.class;
    String string1 = (String) clazz.newInstance();
    // 二:指定的构造函数(不一定带参,自适应):String string2 = new String("hello reflect");
    Constructor constructor = clazz.getConstructor();
    String string2 = (String) constructor.newInstance("hello reflect");
    
    System.out.println(string1 + "
    " + string2);
    //out:空字符串
    //hello reflect
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/quanxi/p/6899830.html
Copyright © 2011-2022 走看看