JAVA高级--反射机制

JAVA高级–反射机制



一、反射是什么?反射有什么用?

  1. 反射机制可以让程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
  2. 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。

1.一般流程与反射流程的对比

在这里插入图片描述

2.反射机制提供主要功能

1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时获取泛型信息
5.在运行时调用任意一个对象的成员变量和方法
6.在运行时处理注解
7.生成动态代理

二、反射的关键类–Class类

上文所说,反射机制是一种可以在运行时获取类信息的机制,而这个Class类我们将它理解成是每一个类对应的信息(Class本身也是一个类),每个类有且只有一个,里面包含了构造器,字段,方法等类的基本信息,我们可以用getClass()方法获取对应信息,然后进行操作。

1.获取Class的几种方式

// 1.知道具体的类,通过具体类的class属性获取对应的Class
        Class hashMapClass = HashMap.class;
        
        // 2.根据类的实例getClass获取对应的Class
        Boolean aBoolean = new Boolean(true);
        Class booleanClass = aBoolean.getClass();
        
        // 3.根据全类名的信息,通过forName查找,(可能抛出异常)
        try
        {
            Class<?> aClass = Class.forName("java.util.concurrent.locks.ReentrantLock");
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }

2.其他类型获取Class

		Class listClass = List.class;// 接口的Class
        Class intClass = Integer.class;// 类的Class
        int arr[] = new int[10];
        Class arrClass = arr.getClass();// 数组Class
        Class enumClass = Month.class;// 枚举Class
        Class baseTypeClass = boolean.class;// 基础数据类型Class
        Class annoClass = Target.class;// 注解Class

3.何种情况出现相同的Class

只要是相同的类或者相同维度的Class,两者是同一个Class,如同样是一维数组,两者是同一个Class

System.out.println(new int[10].getClass() == new int[1000].getClass());//true

三、获取运行时对象信息

  // 获取运行时类的信息
    public static void getClassInfo()
    {
        Student student = new Student();
        Class<? extends Student> studentClass = student.getClass();
        // 实现接口的信息
        Class<?>[] interfaces = studentClass.getInterfaces();
        for (Class<?> anInterface : interfaces)
        {
            System.out.println(anInterface.getName());
        }
        // 父类的信息
        Class<?> superclass = studentClass.getSuperclass();
        System.out.println(superclass.getName());

        // 所有public构造器
        Constructor<?>[] constructors = studentClass.getConstructors();
        // 所有构造器
        Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            //构造器修饰符
            System.out.println(constructor.getModifiers());
            //构造器名称 名字为全类名
            System.out.println(constructor.getName());
            //构造器参数
            for (Class<?> parameterType : constructor.getParameterTypes()) {
                System.out.println(parameterType);
            }
        }

        Method[] methods = studentClass.getMethods();
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            //方法权限
            System.out.println(declaredMethod.getModifiers());
            //方法名
            System.out.println(declaredMethod.getName());
            //方法参数
            for (Class<?> parameterType : declaredMethod.getParameterTypes()) {
                System.out.println(parameterType);
            }
            //返回参数
            System.out.println(declaredMethod.getReturnType());
            //方法抛出的异常
            for (Class<?> exceptionType : declaredMethod.getExceptionTypes()) {
                System.out.println(exceptionType);
            }
        }
        //获取public的属性信息
        Field[] fields = studentClass.getFields();
        //获取所有的属性信息
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            //属性权限
            System.out.println(declaredField.getModifiers());
            //属性类型
            System.out.println(declaredField.getType());
            //属性名称
            System.out.println(declaredField.getName());
        }
    }
public class Student extends People implements Comparable, Cloneable
{

    private String name;

    private String stuNo;

    private Integer age;

    public Student(String name)
    {
        this.name = name;
    }

    private Student(String name, Integer age)
    {
        this.name = name;
        this.age = age;
    }

    Student()
    {
    }

    protected Student(String name, String stuNo, Integer age)
    {
        this.name = name;
        this.stuNo = stuNo;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getStuNo()
    {
        return stuNo;
    }

    public void setStuNo(String stuNo)
    {
        this.stuNo = stuNo;
    }

    public Integer getAge()
    {
        return age;
    }

    public void setAge(Integer age)
    {
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "Student{" + "name='" + name + '\'' + ", stuNo='" + stuNo + '\'' + ", age=" + age + '}';
    }

    @Override
    public int compareTo(Object o)
    {
        return 0;
    }
     private Integer selfIntroduction(String city)
    {
        System.out.println(name + "来自:" + city);
        return age;
    }
}
public class People
{
    private Double money;

    public Double getMoney()
    {
        return money;
    }

    public void setMoney(Double money)
    {
        this.money = money;
    }
}

小结

1.获取属性,构造器,方法权限信息为getModifiers;
2.获取参数列表为getParameterTypes;
3.获取全部权限信息为getDeclared【Fields,Methods,Constructors】()。

四、创建运行时对象

// 3.Class获取对应的构造器
    public static void getConstructorByClass()
            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException
    {
        // 1.获取Class
        Class<Student> studentClass = Student.class;
        // 2.调用指定参数结构的构造器,生成Constructor的实例
        Constructor<Student> constructor1 = studentClass.getConstructor();// 空参构造器实例
        //创建实例
        Student student1 = constructor1.newInstance();
        System.out.println("student1 = " + student1);

        Constructor<Student> constructor2 = studentClass.getConstructor(String.class);// 参数为string的构造器实例
        Student student2 = constructor2.newInstance("小明");
        System.out.println("student2 = " + student2);
    }

五、调用运行时类的指定方法

// 5.调用运行时类的指定方法
    public static void useMethodByClass()
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
    {
        Student student = new Student("夏洛");
        System.out.println(student);
        Class<? extends Student> studentClass = student.getClass();
        Method method1 = studentClass.getMethod("setAge", Integer.class);
        // 返回值
        Object invoke1 = method1.invoke(student, 10);
        System.out.println(invoke1);
        System.out.println(student);

        // 没有参数的方法
        Method method2 = studentClass.getMethod("getName");
        // 返回值
        Object invoke2 = method2.invoke(student);
        System.out.println(invoke2);

        // 私有方法
        Method method3 = studentClass.getDeclaredMethod("selfIntroduction", String.class);
        // setAccessible(true) 将方法设置为显示调用
        method3.setAccessible(true);
        // 返回值
        Object invoke3 = method3.invoke(student, "厦门");
        System.out.println(invoke3);
    }

注:

1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null(或者不填)

六、调用运行时类的指定属性

// 6.调用运行时类的指定属性
    public static void useFieldByClass() throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student("小白");
        System.out.println(student);
        Class<? extends Student> studentClass = student.getClass();
        // 获取字段实例
        Field nameField = studentClass.getDeclaredField("name");
        nameField.setAccessible(true);
        //设置值
        nameField.set(student,"花花");
        System.out.println(student);
    }

注:

1.Method和Field、Constructor对象都有setAccessible()方法;
2.setAccessible启动和禁用访问安全检查的开关。


  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值