Java-Reflect专题

基本反射简介:

1):JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

2):JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言"。从这个观看,Perl,PythonRuby是动态语言,C++,Java,C#不是动态语言。

3):但是JAVA有着一个非常突出的动态相关机制:Reflection用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。

4):换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

Java反射机制提供的功能:

1):在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象

2):在运行时判断任意一个类所具有的成员变量和方法

3):在运行时调用任意一个对象的方法

4):生成动态代理

Class类介绍:

Class 类描述Java程序运行时的所有 Classes 和 interfaces,同时也用来描述enum、array、Java基本数据类型。

生成Class:当一个class文件被加载或者类加载器的defineClass()被JVM调用时,JVM便自动产生一个Class 对象。

常用API:

生成Class对象的方法:

1):根据完整类名获取类,调用 Class 的静态方法 forName():

Class<?> classType = Class.forName(“java.lang.String”);

2):通过类名获取,使用class语法,这里ReflectionTest为一个类名:

Class<?> classType = ReflectionTest.class;

3):通过对象的getClass()方法获取:

User user = new User();
Class<?> classType = user.getClass();
//获取user的父类的Class对象
Class superClass = classType.getSuperclass();

4):对于包装类的Class的获取,使用包装类的TYPE语法:

Class classType = Integer.Type;
Class c = Integer.class;

创建反射获取的类的实例的方法:

1):调用Class的newInstance()方法:

Class c = Class.forName("mlq.Student");
Student student = (Student) c.newInstance();

2):通过Class获取构造方法再实例化:

Class c = Class.forName("mlq.Student");
Student student=(Student)c.getConstructor(new Class[]{}).newInstance(new Object[]{});

提示:当Class数组为空时,本质上等价于①,即调用无参构造函数

获取方法信息函数:

1):获取所有公共方法:

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

Method[] getMethods() -- 获得类的所有公共方法

2):获取所有方法:(不问访问权限)

Method getDeclaredMethod(String name, Class[] params) -使用特写的参数类型,获得类声明的命名的方法

Method[] getDeclaredMethods() -- 获取的是所有该类自己声明的方法,不问访问权限

获取成员变量:

1):获取所有的 public 的成员变量的信息

Field getField(String name) -- 获得指定命名的公共字段

Field[]  getFields()--方法获取的是所有的public的成员变量的信息

2):获取所有成员变量:(不问访问权限)

Field getDeclaredField(String name) -- 获取指定的域,返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段:

Field[]  getDeclaredFields()--获取所有的域,包括公共、保护、默认(包)访问和私有域,但不包括继承的域:

field.setAccessible(true);--设置压制访问控制检查,这样就可以获取和设置私有域的值了:

Field field = classType.getDeclaredField("fieldName");--获取某个对象的域的对应值:

field.get(object);

Field field = classType.getDeclaredField("fieldName");--设置某个对象的域的对应值:
field.set(obj, "arthinking");

获取构造函数信息:

1):获取所有public的函数:

Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,
Constructor[]  getConstructors()
--获取所有的public的构造函数

2):获取构造函数:(不问访问权限)

Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)
Constructor[]  getDeclaredConstructors()
--得到自己声明的构造函数,推荐使用(与接入级别无关)

案例Demo:点我下载源码

1):获取Student类的完整限定名==》全类名

/**
     * 获取Student类的完整限定名==》全类名
     * 01、Class.forName(类的完整限定名) 来加载类 (常用)
     * 02、Student.class 任何类名.class都是获取了Class类
     * 03、new Student().getClass() 任何对象.getClass()都是获取了Class类
     */
    @Test
    public void test01() {
        try {

            System.out.println("打印类的完整限定名、会走静态代码块:" + Class.forName("mlq.Student"));
            System.out.println("====================================");
            System.out.println("只打印类的全名称:" + Student.class);
            System.out.println("====================================");
            System.out.println("无参、静态与非静态块、类完整名称;都会执行" + new Student().getClass().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2):获取包名、类名、访问修饰符值 和 name

/**
     * 获取包名、类名、访问修饰符值 和 name
     */
    @Test
    public void test02() {
        try {
            //加载Student 类
            Class c = Class.forName("mlq.Student");
            System.out.println("Student所在包名称:" + c.getPackage().getName());
            System.out.println("Student全类名:" + c.getName());
            System.out.println("Student类名:" + c.getSimpleName());
            //获取类的访问修饰符
            int num = c.getModifiers();
            System.out.println("public访问修饰符对应的数值:" + num);
            //访问修饰符对相应的名称
            System.out.println(Modifier.toString(num));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

3): 获取类中所有的属性相关信息

/**
     * 获取类中所有的属性相关信息
     */
    @Test
    public void test03() {
        try {
            Class c = Class.forName("mlq.Student");
            //获取所有字段
            Field[] fields = c.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                System.out.println(fields[i]);
            }
            //获取所有字段的访问修饰符
            for (int i = 0; i < fields.length; i++) {
                //修饰符值对象的修饰符名称
                System.out.print(Modifier.toString(fields[i].getModifiers()));
                //访问修饰符对应的数值
                System.out.println(":" + fields[i].getModifiers());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

4):获取类中所有的方法相关信息  不包含构造方法

/**
     * 获取类中所有的方法相关信息  不包含构造方法
     * 01、c.getMethod(方法名称,参数类型)只能是public修饰的
     * 02、c.getMethods()只能是public修饰的
     * 03、c.getDeclaredMethods() 所有
     */
    @Test
    public void test04() {
        try {
            Class c = Class.forName("mlq.Student");
            //获取所有方法,包含private私有的
            Method[] declaredMethods = c.getDeclaredMethods();
            for (int i = 0; i < declaredMethods.length; i++) {
                System.out.println("方法的名称是:" + declaredMethods[i].getName());
                System.out.println("方法的修饰符数值时:" + declaredMethods[i].getModifiers());
                System.out.println("方法的修饰符名称是:" + Modifier.toString(declaredMethods[i].getModifiers()));
                System.out.println("方法的返回值类型是:" + declaredMethods[i].getReturnType());
                System.out.println("=============================================");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

5):获取类中的所有构造方法相关信息

 /**
     * 获取类中的所有构造方法相关信息
     */
    @Test
    public void test05() {
        try {
            Class c = Class.forName("mlq.Student");
            //获取所有构造,包含private私有的
            Constructor[] declaredConstructors = c.getDeclaredConstructors();
            for (int i = 0; i < declaredConstructors.length; i++) {
                System.out.println("构造方法的名称是:" + declaredConstructors[i].getName());
                System.out.println("构造方法的修饰符数值是:" + declaredConstructors[i].getModifiers());
                System.out.print("构造的访问修饰符及参数列表:" + Modifier.toString(declaredConstructors[i].getModifiers()) + "(");
                //获取构造中的参数
                Class[] parameterTypes = declaredConstructors[i].getParameterTypes();
                for (int j = 0; j < parameterTypes.length; j++) {
                    System.out.print(parameterTypes[j].getName() + ",");
                }
                System.out.println(")");
                System.out.println("=======================================");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

6):访问类中私有的属性和方法并且让它执行

/**
     * 访问类中私有的属性和方法并且让它执行
     */
    @Test
    public void test06() {
        try {
            Class c = Class.forName("mlq.Student");
            //Student student=(Student)c.getConstructor(new Class[]{}).newInstance(new Object[]{});
            //实例化
            Student student = (Student) c.newInstance();
            //获取私有字段
            Field userName = c.getDeclaredField("userName");

            //输出字段名称
            System.out.println("输出字段名称:"+userName.getName());
            //打开字段开关
            userName.setAccessible(true);
            //userName.set(student,"abc");
            //输出字段信息
            System.out.println("输出字段信息:"+userName.get(student));
            //获取私有的方法
            Method getSum = c.getDeclaredMethod("getSum", double.class);
            //开启方法开关
            getSum.setAccessible(true);
            //调用执行方法
            double invoke = (Double) getSum.invoke(student, 50.5);
            //输出返回值
            System.out.println(invoke);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.

面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!

12-01 16:20