JAVA高级之反射

反射

  1. 反射之框架的灵魂。
  2. JAVA反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射。
  3. 实质:反射就是加载类,并解析出类的各个部分。

相关概念

框架: 1)就是一些接口和类的集合,通过这些接口和类协调来完成一些列的功能。

​ 2)框架是一个软件半成品,它的出现让我们把主要精力集中于业务逻辑。

反射的好处

1.代码解耦

2.程序运行中操作对象

Java代码的三个阶段

在这里插入图片描述

Source(源码)阶段,此时还在硬盘中

Class(类对象)阶段,此时有类加载器把.class文件加载到内存中,生成类对象

RunTime(运行时)阶段,此时也在内存中,可以执行对象的方法和访问对象的任意成员变量

类的加载

  1. Class,forName(“全类名”)、
  2. 类名.class;
  3. 对象.getClass();
package com.fubo;

public class Demo2 {
    public static void main(String[] args) {
        //加载类
        try {
            //1.方式1
            Class<?> aClass = Class.forName("com.fubo.Demo1");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //1.方式2
        Class<Demo1> demo1Class = Demo1.class;
        //1.方式1
        Demo1 demo1 = new Demo1();
        Class<? extends Demo1> aClass = demo1.getClass();
        System.out.println(aClass);
    }
}

解析类的各个部分(这个是类对象的功能)

解析成员变量

  • Field[] getFields() // 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
  • Field[] getDeclaredFileds() //返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
  • Field getField(String name) // 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
  • Field getDeclaredField(String name) //返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

Field类

封装成员变量的类

常用的方法:

  1. 设置成员变量的值

    void set(Object obj, Object value)

    	// 将指定对象(obj)变量上此    `Field` 对象表示的字段设置为指定的新值。
    
  2. 获取成员变量的值。

    Object get(Object obj)

    //返回指定对象上此     `Field`  表示的字段的值。
    

    3.忽略访问权限符的限制

    void **setAccessible**(boolean flag)
    
    //将此对象的   `accessible` 标志设置为指示的布尔值。
    
  3. 获取字段类型

    Class<?> getType()

    //返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。

package com.fubo;

import com.fubo.com.fubo.entity.Student;

import java.lang.reflect.Field;

public class Demo3 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //1.加载类对象
        Class<Student> studentClass = Student.class;
        //2.解析成员变量
        Field[] fields = studentClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        Student stu  = new Student();
        stu.setUsername("zs");
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName()+","+declaredField.getType());

        }

        Field realname = studentClass.getField("realname");
        //给stu这个变量的realname字段赋值
        realname.set(stu,"好汉");
        System.out.println(realname.get(stu));
        Field username = studentClass.getDeclaredField("username");
        //暴力访问,我们可以操作所有字段
        username.setAccessible(true);
        username.set(stu,"hh");
        System.out.println(username.get(stu));
    }
}

解析构造方法

  • Constructor[] getConstructors()//返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
  • Constructor[]getDeclaredConstructors()// 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
  • ConstructorgetConstructor(Class<?>… parameterTypes) // 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
  • ConstructorgetDeclaredConstructor(Class<?>… parameterTypes)//返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法

Constructor类

封装构造器的类。

常用方法:

  1. 通过构造器创建对象

    T newInstance(Object… initargs)

    //使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

    注:如果是无参构造器,一般不使用此种方法,使用类对象.newInstance()

  2. 忽略访问权限符的限制

    void setAccessible(boolean flag)

    //将此对象的 accessible 标志设置为指示的布尔值。

package com.fubo;

import com.fubo.com.fubo.entity.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo4 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //1.加载类对象
        Class<Student> studentClass = Student.class;
       //2.解析构造器
        Constructor<?>[] constructors = studentClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.toString());
        }

        Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.toString());
        }

        Constructor<Student> constructor = studentClass.getConstructor();

        System.out.println(constructor.toString());
        Constructor<Student> constructor2 = studentClass.getConstructor(String.class,String.class,Integer.class,String.class);
        System.out.println(constructor2.toString());
        Constructor<Student> constructor3 = studentClass.getDeclaredConstructor(String.class);
        System.out.println(constructor3.toString());
        constructor3.setAccessible(true);
        Student lisi = constructor3.newInstance("lisi");
        System.out.println(lisi.getUsername());
        //通过无参构造去创建对象时,推荐使用如下方法,类对象.newInstance();
        Student student = studentClass.newInstance();
    }
}

解析成员方法

  • Method[] getMethods() //返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口的公共方法(包含父类的公共方法)
  • Method[]getDeclaredMethods()// 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
  • Method getMethod(String name, Class<?>… parameterTypes)// 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
  • Method getDeclaredMethod(String name, Class<?>… parameterTypes)// 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

Method类

成员方法的封装类

常用方法:

  1. Object invoke(Object obj, Object… args)

    // 对带有指定参数的指定对象调用由 此 Method 对象表示的底层方法。

  2. 忽略访问权限符的限制

    void setAccessible(boolean flag)

    //将此对象的 accessible 标志设置为指示的布尔值

  3. 获取Method类封装的方法的名称

    String getName()

    // 以 String 形式返回此 Method 对象表示的方法名称。

package com.fubo;

import com.fubo.com.fubo.entity.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

public class Demo5 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //1.加载类对象
        Class<Student> studentClass = Student.class;
       //2.解析成员方法
        Method[] methods = studentClass.getMethods();
      /*  for (Method method : methods) {
            System.out.println(method.toString());
        }*/

        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }

        Student student = studentClass.newInstance();

        Method say = studentClass.getMethod("say");
        say.invoke(student);

        Method say2 = studentClass.getMethod("say",String.class);
        say2.invoke(student,"我什么也不想说");

        Method say3 = studentClass.getDeclaredMethod("say",String.class, Date.class);
        say3.setAccessible(true);
        say3.invoke(student,"我什么也不想说",new Date());
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值