Loading

Java-反射机制

基本概念

  • 通常情况下编写代码都是固定的,无论运行多少次执行的结果也是固定的,在某些特殊场合中编写代码时不确定要创建什么类型的对象,也不确定要调用什么样的方法,这些都希望通过运行时传递的参数来决定,该机制叫做动态编程技术,也就是反射机制。
  • 通俗来说,反射机制就是用于动态创建对象并且动态调用方法的机制。
  • 目前主流的框架底层都是采用反射机制实现的。
  • 如:
    Person p= new Person(); //表示声明 Person类型的引用指向 Person类型的对象
    p.show(); // 表示调用 Person类中的成员方法show

Class类

甚本概念

  • java.lang.Class类的实例可以用于描述java应用程序中的类和接口,也就是一种数据类型。
  • 该类没有公共构造方法,该类的实例由java虚拟机和类加载器自动构造完成,本质上就是加载到内存中的运行时类。

获取 Class对象的方式

  • 使用数据类型.class的方式可以获取对应类型的 Class对象
  • 使用引用/对象.getClass()的方式可以获取对应类型的Class对象。
  • 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象
  • 使用 Class.forName 的方式来获取参数指定类型的Class象
  • 使用类加载器 ClassLoader 的方式获取指定类型的Class对象

常用方法

方法声明 功能介绍
static Class< ? > forName(String className) 用于获取参数指定类型对应的class对象并返回
T newInstance() (已过时 请使用Constructor类)用于创建该Cass对象所表示类的新实例

Constructor类

基本概念

  • java.lang.reflect.Constructor类主要用于描述获取到的构造方法信息。

Class类的常用方法

方法声明 功能介绍
Constructor< T > getConstructor( Class< ? >...parrmeterTypes) 用于获取此Class对象所表示类型中参数指定的公共构造方法
Constructor< ? > [] getConstructors() 用于获取此Class对象所表示类型中所有的公共构造

Constructor类的常用方法

方法声明 功能介绍
T newInstance(object...initargs) 使用此 Constructor对象描述的构造方法来构造Cass对象代表类型的新实例
int getModifiers() 获取方法的访问修饰符
String getName() 获取方法的名称
Class< ? >[] getParameterType() 获取方法所有参数的类型

使用反射机制创建实例

import java.io.*;
import java.lang.reflect.Constructor;

public class PersonTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            // 文件字节输入流
            fis = new FileInputStream("./config.txt");
            // 将文件字节输入流转换为 Reader 输入流
            isr = new InputStreamReader(fis);
            // 使用字符缓冲加载输入流
            br = new BufferedReader(isr);
            // 获取配置文件第一行
            String line = br.readLine();
            // 将配置文件中的类动态加载
            Class forName = Class.forName(line);
            System.out.println("动态加载的类为:" + forName); // class task4.reflect.Person
            // 获取Class对象的无参构造方法,也就是Person的无参构造方法
            Constructor constructor = forName.getConstructor();
            // 使用获取到的无参构造方法构造相应类型的对象也就是Person类型的对象
            System.out.println("使用无参构造的对象是:" + constructor.newInstance());
            // 通过有参构造获取对象 按传入参数选择对应的构造
            Constructor constructor1 = forName.getConstructor(int.class, String.class);
            System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10,"feng"));

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != fis) {
                    fis.close();
                }
                if (null != isr) {
                    isr.close();
                }
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

Field 类

基本概念

java.lang.reflect.Field类主要用于描述获取到的单个成员变量信息。

Class类的常用方法

方法声明 功能介绍
Field getDeclaredField(String name) 用于获取此Cas对所表示类中参数指定的单个成员变量信息
Field getDeclaredFields() 用于获取此Class对象所表示类中所有成员变量信息

Field类的常用方法

方法声明 功能介绍
Object get(Object obj) 取参数对象Object中此Field对象所表示成员变量的数值
void set(Object obj, Object value) 将参数对象Object中此Field对象表示成员变量的数值修改为参数vlaue的数值
void setAccessible(boolean flag) 当实参传通true时,则反射对象在使用时应该取消Java语言访问检查
int getModifiers() 获取成员变量的访问修饰符
Class< ? > getType() 获取成员变量的数据类型
String getName() 取成员变量的名称

获取和修改成员变量

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class PersonTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            // 文件字节输入流
            fis = new FileInputStream("./config.txt");
            // 将文件字节输入流转换为 Reader 输入流
            isr = new InputStreamReader(fis);
            // 使用字符缓冲加载输入流
            br = new BufferedReader(isr);
            // 获取配置文件第一行
            String line = br.readLine();
            // 将配置文件中的类动态加载
            Class forName = Class.forName(line);
            // 通过有参构造获取对象 按传入参数选择对应的构造
            Constructor constructor1 = forName.getConstructor(int.class, String.class);
            System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10, "feng"));

            // 有参构造创建对象
            Object object = constructor1.newInstance(10, "feng");
            // 获取成员变量
            Field field = forName.getDeclaredField("name");
            // 获取对象 object 中名字为 filed 的数值,也就是成员变量name中的值
            // 如果是private没有权限访问 异常,需要反射时调用setAccessible(true);取消java访问检查
            field.setAccessible(true); // 取消 java 访问检查
            Object v = field.get(object);
            System.out.println("获取到成员变量的值为:" + v);

            // 修改成员变量
            field.set(object, "li");
            v = field.get(object);
            System.out.println("修改后的成员变量值为:" + v);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != fis) {
                    fis.close();
                }
                if (null != isr) {
                    isr.close();
                }
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

Method类

基本概念

java.lang.reflect.Method类主要用于描述获取到的个成员方法信息。

Class类的常用方法

方法声明 功能介绍
Method getMethod(String name, Class< ? >...parameterTypes) 用于获取该Class对象表示类中名字为name参数为parameterTypes的指定公共成员方法
Method getMethods() 用于获取该Cass对象表示类中所有公共成员方法

Method类的常用方法

方法声明 功能介绍
Object invoke(Object obj, Object...args) 使用对象obj来调用此 Method对象所表示的成员方法,实参传递args
int getModifiers() 获取方法的访问修饰符
Class< ? > getReturnType() 获取方法的返回值类型
String getName() 获取方法的名称
Class< ? > getParameterTypes() 获取方法所有参数的类型
Class< ? > getExceptionTypes() 获取方法的异常信息

获取方法及调用方法

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PersonTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            // 文件字节输入流
            fis = new FileInputStream("./config.txt");
            // 将文件字节输入流转换为 Reader 输入流
            isr = new InputStreamReader(fis);
            // 使用字符缓冲加载输入流
            br = new BufferedReader(isr);
            // 获取配置文件第一行
            String line = br.readLine();
            // 将配置文件中的类动态加载
            Class forName = Class.forName(line);
            // 通过有参构造获取对象 按传入参数选择对应的构造
            Constructor constructor1 = forName.getConstructor(int.class, String.class);
            System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10, "feng"));

            // 有参构造创建对象
            Object object = constructor1.newInstance(10, "feng");
            // 获取方法有参方法
            Method setName = forName.getMethod("setName", String.class);
            // 获取无参方法
            Method getName = forName.getMethod("getName");
            // 调用方法
            setName.invoke(object, "Hello");
            Object invoke = getName.invoke(object);
            System.out.println("获取到的值为:" + invoke);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != fis) {
                    fis.close();
                }
                if (null != isr) {
                    isr.close();
                }
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}

获取其它结构信息

方法声明 功能介绍
Package getPackage() 获取所在的包信息
Class< ? super T > getSuperClass() 获取继承的父类信息
Class< ? >[] getInterfaces() 获取实现的所有接口
Annotation[] getAnnotations() 获取注解信息
Type[] getGenericInterfaces() 获取泛型信息
posted @ 2021-09-12 12:04  白日醒梦  阅读(48)  评论(0编辑  收藏  举报