Java 反射

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

反射的背景信息

servlet没有主方法(main) ,靠自己运行不起来,所以要引入 tomcat(Java写的带有java主方法的程序),依靠其运行,产生一系列关联性调用。

tomcat如何运行servlet?

正常:人眼可以清楚的看到类、对象、属性的名字,new一个类的对象,然后用类的对象调用。

tomcat : 不知道 servlet 的名称,不能new,只能用自己的工具,于是反射的作用出现了,用反射获取信息。

反射能获取到哪些信息呢? 凡是人眼能看到的都可以获取。

什么是java反射? 能够分析类信息的能力叫做反射。

为什么类信息存储在方法区当中?

.class文件叫做二进制字节码文件,首先进入方法区,实际上分为三个过程:

✔️ 硬盘阶段

class.forName("全类名")

✔️ class类对象阶段

进行封装,内部生成类对象(全局变量Field对象、构造器constructor、方法method)

类名.class

✔️ 运行时阶段

对象名.getClass

反射获取类信息的方式!!!

反射获取类信息的方式有 3 种:

  1. 通过对象的getClass方法进行获取

  2. 通过Class.forName()方法获取:调用静态方法 forName 获得类名对应的 Class 对象。

  3. 通过静态属性class可直接获取到该类型对应的Class对象 例如:T.class 将代表匹配的类对象

💡 tomcat 使用第二种方法,扫描所有目录,找到.class文件

非静态的方法必须依靠对象来执行,通过newInstance()获取类的对象

反射是否可以获得类的私有信息?

是可以的,把 .setAccessible() 方法设置成true

具体方法内容

1. 反射要想获取类信息,就必须生成类对象

2. 三种方式获取类对象:

◼️ 磁盘节点

Class class1 = Class.forName("com.qcby.Person");

◼️ 类对象阶段

Class class2 = Person.class;

◼️ 运行时阶段

Person person = new Person();
Class class3 = person.getClass();

3. 用三种阶段的对象获取类信息

    Field[] fields1 = class1.getDeclaredFields();
        for (Field field:fields1){
            System.out.println(field);
    }
    
    Field[] fields2 = class2.getDeclaredFields();
    for (Field field:fields2){
        System.out.println(field);
    }
   
    Field[] fields3 = class3.getDeclaredFields();
    for (Field field:fields3){
        System.out.println(field);
    }

获取全局变量信息的方式 Field

1. 类对象.getDeclaredFields()

获取所有的全局变量 需要使用Filed[]接收

2. 类对象.getFields()

获取所有的public修饰的全局变量 需要使用Filed[]接收

3. 类对象.getDeclaredField(“变量名”)

能够获取指定的任何修饰符修饰的全局变量信息 需要使用Filed接收

4. 类对象.getField(“变量名”)

能够获取指定的public修饰符修饰的全局变量信息 需要使用Filed接收

返回获取方法 Method

1. 类对象.getDeclaredMethods() :

这种方式获取所有的方法信息 Method[]

2. 类对象.getMethods() :

这种方式 获取public修饰的 方法信息 Method[]

3. 类对象.getDeclaredMethod("方法名",所有参数的类型)

获取所有的指定的方法信息 Method

4. 类对象.getMethod("方法名",所有参数的类型)

获取public的指定的方法信息 Method

返回获取构造器

1. 类对象.getDeclaredConstructors() :

这种方式获取所有的构造器信息 Constructor[]

2. 类对象.getConstructors() :

这种方式获取public修饰的构造器信息 Constructor[]

3. 类对象.getDeclaredConstructor("方法名",所有参数的类型)

获取所有的指定的构造器信息 Constructor

4. 类对象.getConstructor("方法名",所有参数的类型)

获取public的指定的构造器信息 Constructor

如何创建对象?

变量的赋值和取值操作

set() 和 get()

暴力反射,修改类中对象的姓名(私有属性),使用 getDeclaredFields() !!! 和 setAccessible(true)

一:只有变量时

public class Abc {
    private String name;

    @Override
    public String toString() {
        return "Abc{" +
                "name='" + name + '\'' +
                '}';
    }
}

class TestAbc{
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        
        Abc a = new Abc();
        // 补全
        // 把名字设置成张三
        Class c1 = a.getClass();
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);
        name.set(a,"张三");
        System.out.println(a.toString());
    }
}

二:有构造方法时

如何执行方法? 使用 invoke()

public class Abc {
    private String name;

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

    @Override
    public String toString() {
        return "Abc{" +
                "name='" + name + '\'' +
                '}';
    }
}

class TestAbc{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException {
        
        Abc a = new Abc();
        //补全
        //把名字设置成张三
        Class c1 = a.getClass();
        Method method = c1.getDeclaredMethod("setName", String.class);
        method.setAccessible(true);
        method.invoke(a,"张三");
        System.out.println(a.toString());
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值