• 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
  • 相关阅读:
    MASM32_SDKv10以及一些帮大家打包的东西
    Visual C++6.0 with SP6(中英文版)
    Code::Blocks(完全取代VC6的开源跨平台编程利器)
    汇编学习必备 汇编金手指
    Visual C++6.0 with SP6(中英文版)
    汇编学习必备 汇编金手指
    Code::Blocks(完全取代VC6的开源跨平台编程利器)
    Masm5.0、6.15 汇编语言编译器
    [原创 flash] 用flash制作mp3音乐播放器
    php中,将string转变成date
  • 原文地址:https://www.cnblogs.com/quanxi/p/6899830.html
Copyright © 2020-2023  润新知