JavaSE之反射(框架实现的基础)

反射(框架实现的基础)

什么是反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制(注意关键词:运行状态)换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods

反射:将类的各个组成部分封装为其他对象,反射机制

这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制

疑惑:就是真的要每一个请求都写一个Servlet去接收吗?那不是很麻烦?一个是类多,同一放在了web包管理起来很难(当时想的一个效果就是能不能用一个Servlet去接收全部的请求,而且这个Servlet有全部请求得处理方法)

写的这个mvc:想实现一个目的地,就是要简单,方便得解决上面得问题

设想就是说,我们有一个Servlet类,在接收到请求之后会找到对应得处理请求的方法的话,那就可以解决了

这样的话就是把处理请求的方法看作一个个类,然后建立对应关系

实现要求:

  1. ​ 能识别出不同请求的具体名字java里uri
  2. ​ 处理请求的方法类一定要提前创建在内存里(如果new代表着你要在接收到请求,判断之后才把类创建出来。等待时间肯定很长)

java代码在计算机中经历的三个阶段

在这里插入图片描述
blog.csdnimg.cn/20200815172616217.png#pic_center)

反射的一个具体应用:

类的字节码加载进了虚拟机,然后将类的方法封装成一个个类,然后展示出来
在这里插入图片描述在这里插入图片描述

反射的好处

  1. 可以在程序运行过程中,操作这些对象。
  2. 可以解耦,提高程序的可扩展性

获取Class对象的方式

  1. Class.forName(“全类名”);将字节码文件加载进内存,返回Class对象
    • 多用于配置文件,将类名定义在配置文件中,读取文件,返回Class对象
  2. 类名.class;通过类名的属性class获取
    • 多用于参数的传递
  3. 对象.getClass();继承Object的getClass()方法
    • 多用于对象的获取字节码的方式
//1. Class.forName(“全类名”)
        Class cla = Class.forName("com.zhq.test.Person");

        //2. 类名.class
        Class cla1 = Person.class;

        //3. 对象.getClass()
        Person person = new Person();
        Class cla2 = person.getClass();
        
        System.out.println(cla);
        System.out.println(cla1);
        System.out.println(cla2);
        
        //比较三个对象
        System.out.println(cla == cla1);
        System.out.println(cla == cla2);

在这里插入图片描述
在这里插入图片描述
从内存地址一样可以看出来,三种方式的获取Class类对象都是同一个,说明同一个字节码文件(*.class)在一次程序运行过程中,只会加载一次,不论是通过哪一种方式获取Class对象都是同一个

Class对象功能

获取功能:

  1. 获取成员变量

    • getFields() 获取所有public修饰的成员变量
    • getField(String name) 获取所有的成员变量
    • getDeclaredFields()
    • getDeclaredField(String name)
  2. 获取构造方法

    • getConstructors()
    • getConstructor(类<?>... parameterTypes)
    • getDeclaredConstructors()
    • getDeclaredField(String name)
  3. 获取成员方法

    • getMethods()
    • getMethod(String name, 类<?>... parameterTypes)
    • getDeclaredMethods()
    • getDeclaredMethod(String name, 类<?>... parameterTypes)
  4. 获取类名

    • getName() 获取类名

    • getPackageName() 获取包名

//一个Person类
public class Person {
    private String name;
    private int age;
	public int id;
    public Person(){};
    
    public void eat(){
    	System.out.println("eat..".)
    };
}
Field:成员变量
//获取Person的s对象
        Class personClass = Person.class;
//获取public修饰的成员变量
Field[] fields = personClass.getFields();
        for (Field field:fields) {
            System.out.println(field);
        }

在这里插入图片描述

//获取所有成员变量getDeclaredFields()
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField:declaredFields) {
            System.out.println(declaredField);
        }

在这里插入图片描述

这个对象的操作(作用):
  1. 设置值
    • set(Object obj, Object value)
  2. 获取值
    • get(Object obj)
  3. 忽略访问权限修饰符的安全检查
    • setAccessible(true)

操作public修饰的变量

//获取public成员变量id的值
        Field id = personClass.getField("id");
        Person p = new Person();
        Object value = id.get(p);
        System.out.println(value); //预计是0
//设置public成员变量id的值
        id.set(p,123456);
        System.out.println(p);

在这里插入图片描述

操作私有private变量(需要忽略访问权限修饰符的安全检查)

Field name = personClass.getDeclaredField("name");
        //忽略访问权限修饰符的安全检查
        name.setAccessible(true);//暴力反射,如果不加会报IllegalAccessException
        Object value1 = name.get(p);
        System.out.println(value1);
        name.set(p,"张三");
        System.out.println(value1);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jMlks3QB-1597483444398)(C:\Users\zhqsocool\AppData\Roaming\Typora\typora-user-images\image-20200815160028385.png)]

Constructor:构造方法
创建对象:
  • newInstance(Object... initargs)

注意如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance方法

		//getConstructor(类<?>... parameterTypes)
		Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person);

在这里插入图片描述

Method:成员方法
执行方法:
  • invoke(Object obj, Object... args)
获取方法名:
  • get name()
//getMethod(String name, 类<?>... parameterTypes)
        Method eat = personClass.getMethod("eat");
        Person p = new Person();
        //执行空参方法
        eat.invoke(p);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9EurEjE3-1597483444403)(C:\Users\zhqsocool\AppData\Roaming\Typora\typora-user-images\image-20200815162313740.png)]

Method eat_method = personClass.getMethod("eat", String.class);
        //一参方法
        eat_method.invoke(p,"苹果");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VF6t6HGR-1597483444417)(C:\Users\zhqsocool\AppData\Roaming\Typora\typora-user-images\image-20200815162631129.png)]

//获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method:methods) {
            System.out.println(method);
        }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值