阶段三/Java反射

目录

反射的核心类

Class类

Class核心方法

Constructor构造方法类

Constructor类的核心方法

Method方法

Method类核心方法

Field成员对象类

Field类核心方法

getDeclared系列方法


反射的核心类

  • Class类
  • Constructor构造方法类
  • Method方法类
  • Field成员变量类

Class类

  1. Class是JVM中代表“类和接口”的类
  2. Class对象具体包含了某个特定类的结构信息
  3. 通过Class对象可获取对应类的构造方法/方法/成员变量

Class核心方法

  • Class.forName():静态方法,用于获取指定Class对象
  • classObj.newInstance():通过默认构造方法创建新的对象
  • classObj.getConstructor():获得指定的public修饰构造方法Constructor对象
  • classObj.getMethod():获取指定的public修饰方法Method对象
  • classObj.getField():获取指定的public修饰成员变量Field对象。

1.通过Class.forName()方法将指定的类加载到jvm(可以给指定类加静态代码块来看效果,静态块随着类的加载而加载),并返回对应Class对象,如下例的employeeClass

2.通过Class的对象的newInstance方法调用指定类的默认构造函数进行实例化,返回一个Object类的对象,需要强转成指定类

Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
System.out.println("Employee已被加载到jvm");
//通过类对象调用newInstance方法,再通过默认构造方法创建新的对象,返回的是Object,需要强转
Employee emp = (Employee)employeeClass.newInstance();
System.out.println(emp);

Constructor构造方法类

  • Constructor类是对Java类中的构造方法的抽象
  • Constructor对象包含了具体类的某个具体构造方法的声明
  • 通过Constructor对象调用代参构造方法创建对象

Constructor类的核心方法

  • classObj.getConstructor():获取指定public修饰的构造方法对象
  • ConstructorObj.newInstance():通过对应的构造方法创建对象。classObj.newInstance()是调用默认构造方法创建对象,带参的还是得通过ConstructorObj.newInstance()创建。

1.通过Class.forName()方法将指定的类加载到jvm,并返回对应Class对象,如下例的employeeClass

2.通过Class类的对象调用getConstructor方法,获得指定的public修饰构造方法Constructor对象(需要通过Class数组描述想要调用的带参构造方法的参数类型,顺序要能与带参构造方法对上)。

3.通过Constructor对象的newInstance方法调用指定类的带参构造函数进行实例化,需要给出对应构造方法的实参。

Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
// 调用带参构造方法,但是带参构造方法可能不止一个,需要通过Class数组,描述参数的数量及对应的类型
// 得到指定格式的带参构造
Constructor constructor= employeeClass.getConstructor(new Class[]{
    //对于已有的类来说已被加载,自然可以通过.class属性得到对应的类对象
    Integer.class, String.class, Float.class, String.class
});
// 通过Constructor对象的newInstance方法,调用包含4个参数的构造方法实例化对象
Employee employee = (Employee)constructor.newInstance(new Object[]{
    100, "李东", 3000f, "研发部"
});
System.out.println(employee);

Method方法

  • Method对象指代某个类中的方法的描述
  • Method对象使用classObj.getMethod()方法获取
  • 通过Method对象调用指定对象的对应方法

Method类核心方法

  • classObj.getMethod():获取指定public修饰的方法对象
  • methodObj.invoke():调用指定对象的对应方法

1.通过Class.forName()方法将指定的类加载到jvm,并返回对应Class对象,如下例的employeeClass

2.通过Class类的对象调用getConstructor方法,获得指定的public修饰构造方法Constructor对象。

3.通过Constructor对象的newInstance方法调用指定类的带参构造函数进行实例化。

4.通过Class类的对象调用getMethod方法获取指定public修饰的方法对象,需要给出两类参数,第一个参数是指定方法的名字,以字符串形式给出,以及一个Object数组,里面给出与指定方法对应的参数的类型

5.通过Method的对象,调用invoke方法,即调用指定对象的对应方法,需要给出两类参数:相关类的对象,Object数组,里面是该对象的指定方法的实参。

Class employeeClass= Class.forName("com.imooc.reflect.entity.Employee");
Constructor constructor = employeeClass.getConstructor(new Class[]{
    Integer.class, String.class, Float.class, String.class
});
Employee emp = (Employee)constructor.newInstance(new Object[]{
    100, "李东", 9000.0f, "研发部"
});
System.out.println(emp);
//通过Class类的对象调用getMethod方法获取指定public修饰的方法对象,需要给出两类参数,
// 第一个参数是指定方法的名字,以字符串形式给出,以及一个Object数组,
// 里面给出与指定方法对应的参数的类型
Method updateSalaryMethod = employeeClass.getMethod("updateSalary", new Class[]{Float.class});
// 通过Method的对象,调用invoke方法,即调用指定对象的对应方法,
// 需要给出两类参数:相关类的对象,Object数组,里面是该对象的指定方法的实参。
emp = (Employee) updateSalaryMethod.invoke(emp, new Object[]{500.0f});
System.out.println(emp);

Field成员对象类

  • Field对应某个具体类中的成员变量的声明
  • Field对象使用classObj.getField方法获取
  • 通过Field对象可为某对象成员变量赋值/取值

Field类核心方法

  • classObj.getField():获取指定public修饰的成员变量对象
  • fieldObj.set():为某对象指定成员变量赋值
  • fieldObj.get():获取某对象指定成员变量数值

1.通过Class.forName()方法将指定的类加载到jvm,并返回对应Class对象,如下例的employeeClass

2.通过Class类的对象调用getConstructor方法,获得指定的public修饰构造方法Constructor对象。

3.通过Constructor对象的newInstance方法调用指定类的带参构造函数进行实例化。

4.通过Class的对象调用getField方法,得到Field类的对象,需要给出参数,指定的成员变量名称。

5.通过Field的对象调用get方法,获取对应的成员变量的值。需要给出指定的对象

6.通过Field的对象调用set方法,设置对应成员变量的值,需要给出指定的对象,以及实参。

Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
Constructor constructor= employeeClass.getConstructor(new Class[]{
    //对于已有的类来说已被加载,自然可以通过.class属性得到对应的类对象
    Integer.class, String.class, Float.class, String.class
});
Employee employee = (Employee)constructor.newInstance(new Object[]{
    100, "李东", 3000f, "研发部"
});
// 通过Class类的对象获取指定public修饰的成员变量对象,需要给出String类型的成员变量的名字
Field nameField= employeeClass.getField("ename");
System.out.println(employee);
// 通过成员变量对象的set方法,需要给出两个参数,指定的对象,实参,来设置指定对象的指定成员变量
nameField.set(employee, "Lucy");
// 通过成员变量对象的get方法,只要给出一个参数,指定的对象,就可以获取指定对象的指定的成员变量
System.out.println((String)nameField.get(employee));
System.out.println(employee);

getDeclared系列方法

  • getDeclaredConstructor(s) | Method(s) | Field(s):获取对应对象
  • getConstructor(s) | Method(s) | Field(s):只能获取public对象
  • 访问非作用域内构造方法、方法、成员变量,会抛出异常
  1. 通过Class.forName()方法将指定的类加载到jvm,并返回对应Class对象,如下例的employeeClass
  2. 通过Class类的对象调用getConstructor方法,获得指定的public修饰构造方法Constructor对象。
  3. 通过Constructor对象的newInstance方法调用指定类的带参构造函数进行实例化。
  4. 通过Class类的对象调用getDeclaredFields方法,得到Field对象的数组,每一个元素是一个成员变量的信息,包括修饰符、类型、名字(包名+类名+成员变量名),例如:private java.lang.Integer com.imooc.reflect.entity.Employee.eno,可以获取到所有的成员变量的信息
  5. public修饰的和非public修饰的访问的方法不一样,通过getModifiers()方法的返回值判断修饰符
    1. 对于修饰符是public的即getModifiers()为1的,可以直接通过field对象get方法访问成员变量的值,需要传入指定的对象
    2. 对于修饰符是private的,外部不能直接访问成员变量,而是需要借助指定对象的public修饰的get和set方法。例如此处我们先要拼出get方法的名称,通常是get+成员变量名的首字母大写。通过field对象的getName方法可以拿到成员变量名,就可以拼出方法名。这边需要借助Method类的对象。先通过Class类的对象调用getMethod得到Method的对象,在通过Method的对象调用invoke,运行指定对象的指定方法拿到结果。
Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
Constructor constructor= employeeClass.getConstructor(new Class[]{
    //对于已有的类来说已被加载,自然可以通过.class属性得到对应的类对象
    Integer.class, String.class, Float.class, String.class
});
Employee employee = (Employee)constructor.newInstance(new Object[]{
    100, "李东", 3000f, "研发部"
});
// 获取所有的成员变量的信息
Field[] fields= employeeClass.getDeclaredFields();
for(Field field: fields){
    System.out.println(field);
}

for(Field field: fields){
    // field.getModifiers()获取修饰符,返回整书类型
    if(field.getModifiers() == 1){ // public修饰
        // public的可以直接获取
        System.out.println(field.getName() + ": " + field.get(employee));
    }else if(field.getModifiers() == 2){ // private修饰
        // private的成员变量,需要借助他们的public修饰的get方法
        // 拼private修饰的成元变量的public的get方法的方法名
        String methodName = "get" + field.getName().substring(0, 1).toUpperCase()
                            + field.getName().substring(1);
         // 获取指定方法名的Method对象,get没有参数,由于是可变列表,只需要传指定对象即可
         Method method= employeeClass.getMethod(methodName);
         // Method对象调用invoke,调用指定的方法,此处不能强转,因为get返回值类型不同
         System.out.println(field.getName() + ": " + method.invoke(employee));
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值