Java—反射
创始人
2024-03-17 02:12:46
0

文章目录

  • 什么是反射
    • 反射定义
  • java创建对象的三个阶段
  • 反射过程
    • 反射第一步:获取类对象
      • 获取类对象的三种方式
    • 反射第二步:获取类信息
      • 如何获取类信息?
        • 1、获取成员变量:
        • 2、获取方法:
        • 3、获取构造器
    • 反射第三步:使用反射信息
      • 1、使用构造器 / 如何使用构造器 (构造器主要是用来创建对象的)
      • 2、方法的使用 / 如何使用方法
      • 3、变量的使用 / 如何使用变量 ----赋值、取值

——————————————————————————

什么是反射

  1. servlet是怎么运行的呢?
    ——> servlet里面没有main方法
    ——>servlet运行就用到了反射
    在这里插入图片描述
    private——私有的
    public——公开的
    protected——受保护的
    String password——default默认为空的
  2. 如何给这些数据赋值?
    2.1 创建一个对象进行赋值
    ——> 通过对象调用变量 或者 改变了的set()方法进行赋值
    ——>
    private类型的可以创建方法
    2.2 利用反射赋值
    所谓的反射赋值其实就是通过获取类信息,然后创建对象,通过对象给获取到的类信息赋值

反射定义

反射:拥有获取类信息的能力
创建对象的流程:
1、自定义java文件—>demo.java—>javac命令编译成demo.class——>通过.java命令运行到JVM内存(加载到方法区,方法区存储的是类信息 (类对象) )
(简单理解为:从类到对象的过程)
2、main方法入栈——>main方法创建类student对象——>student对象在堆内存中开辟内存空间——>堆当中,对象内部有变量的空间,存有变量(name,age,password,sno,age)

java创建对象的三个阶段

  1. 磁盘阶段 - - - - - -在d盘或在c盘等磁盘当中
  2. 类对象阶段 - - - - - -加载到内存的阶段
  3. 运行阶段
    (在堆内存那块内存区域的叫做对象,方法区当中是类对象)
    为什么一个类可以创建多个对象???——>因为类对象时刻保存在方法区当中,所以才可以时刻创建出多个对象

反射过程

反射第一步:获取类对象

获取类对象的三种方式

如何获取类对象?
方式一:通过Class.forName(“全类名”)变量来获取类对象(全类名:包名+类名)------(对应磁盘阶段,磁盘阶段就是地址形式进行存储)
方式二:类名.class ------ 类本身已经构建成了类对象,加载到磁盘当中了,因此不需要写全类名,直接类名.class就能获取类对象(对应类对象阶段)
方式三: 对象名.getClass ------ 已经生成了对象,(回退)(对应运行阶段)

反射第二步:获取类信息

如何获取类信息?

1、获取成员变量:

想获取成员变量——>通过Field类/类对象提供了一些方法
—1—>类对象.getDeclaredFields(); -------获取所有的变量,由Field[]数组进行接收
Field[] fields = class1.getDeclaredFields();
—2—>类对象.getFields(); -------获取全部的public修饰的变量,由Field[]数组进行接收
Field[] fields1 = class1.getFields();
—3—>类对象.getDeclaredField(“参数”); -------获取指定的变量,参数为指定变量名,由Field变量进行接收
Field name = class1.getDeclaredField(“name”);
—4—>类对象.getField(“参数”); -------获取指定的public修饰的变量,参数为指定变量名,由Field变量进行接收
Field password= class1.getField(“password”);
总结:方法上有Declared能获取全部的,没有Declared只能获取public修饰的变量
当sno是protected类型的时候
Field sno = class1.getField(“sno”);//会报错

2、获取方法:

—1—>类对象.getDeclaredMethods() ---------获取全部的方法,由Method[]数组接收
Method[] methods = class1.getDeclaredMethods();
—2—>类对象.getMethods() ---------获取全部的public修饰的方法,由Method[]数组接收
Method[] methods = class1.getMethods();
—3—>类对象.getDeclaredtMethod(“方法名”,“该参数的反射类型 . 该方法的参数”) ---------获取指定的方法,所有类型都可以获取,由Method变量进行接收
( 方法没有参数的时候就不写后面的"参数的类型 . 该方法的参数" )
—4—>类对象.getMethod(“方法名”,“该参数的反射类型 . 该方法的参数”) ---------获取指定的public类型修饰的方法,由Method变量进行接收

3、获取构造器

—1—>类对象.getDeclaredConstructors() ---------获取全部的构造方法,由Constructor[]数组接收
Constructor[] Constructor = class1.getDeclaredConstructors();
—2—>类对象.getConstructors() ---------获取全部的public修饰的构造方法,由Constructor[]数组接收
Constructor[] Constructor = class1.getConstructors();
—3—>类对象.getDeclaredConstructor(该参数的反射类型) ---------获取指定的构造方法,由Constructor变量接收
Constructor Constructor = class1.getDeclaredConstructor();
—4—>类对象.getConstructor(该参数的反射类型) ---------获取指定的public类型的构造方法,由Constructor变量接收
Constructor Constructor = class1.getConstructor();
所有构造器的方法名是一样的

反射第三步:使用反射信息

1、使用构造器 / 如何使用构造器 (构造器主要是用来创建对象的)

通过调用newInstance()方法来创建对象(constructor.newInstance();)
Student student = (Student) constructor.newInstance();//利用构造器生成对象
如果想要使用私有类型的数据,必须使用暴力反射
——》constructor.setAccessible(true);
对于私有的数据,必须使用暴力反射才能使用,不是私有类型的数据,不需要使用暴力反射

Class clazz = Class.forName("fanshe.com.Student");
Constructor constructor = clazz.getDeclaredConstructor();
//如果想要使用私有类型的数据,必须使用暴力反射
constructor.setAccessible(true);
Student student  = (Student) constructor.newInstance();//利用构造器生成对象
System.out.println(student.sex);//这样才能使用

注:(总结)
构造器本质:创建对象
1、获取指定的构造器:如果是public修饰的,用getConstructor(“参数的反射类型”),如果是非public修饰的用getDeclaredConstructor(“该参数的反射类型”)
2、通过调用newInstance()方法来创建对象------newInstance(参数的值):如果是private类型修饰的构造器,需要暴力反射。
【获取到的指定构造器名.setAccessible(true);】
3、想使用public 和 protected 等非私有类型修饰的数据 ------ :不需要使用暴力反射

2、方法的使用 / 如何使用方法

调用invoke(对象,该方法的参数)方法 用来执行指定的方法

Class clazz = Class.forName("fanshe.com.Student");
Method method = clazz.getMethod("eat",String.class);//为什么要创建对象??——》获取类信息是处在类对象阶段,方法、变量在第三阶段
//因为获取的类信息来源于第二阶段(对象阶段),但是要使用方法需要进入到第三阶段,创建对象,给方法内存空间才能进行调用
Student student = new Student("张三");
method.invoke(student,"水果"); 
———————————————以上是不使用反射的时候,使用反射是下面这样———————————————————————
Class clazz = Class.forName("fanshe.com.Student");
Constructor construcor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance();//调用newInstance()来创建当前对象
method.invoke(student,"水果");--------
Student.java当中有:
private Student(){}

注:
1、获取指定所有的方法
2、创建对象 -------为什么要创建对象??——》因为获取的类信息来源于第二阶段(对象阶段),但是要使用方法需要进入到第三阶段,创建对象,给方法内存空间才能进行调用,所以需要提前创建出对象
3、如果是private类型修饰,需要暴力反射 ,如果是其他类型不需要暴力反射
4、调用invoke方法---------获取的方法类信息.invoke(对象,参数的值…);

3、变量的使用 / 如何使用变量 ----赋值、取值

Class clazz = Class.forName("fanshe.com.Student");
//获取类信息
Field field = clazz.getDeclaredField();
field.setAccessible(true);
//赋值 set方法
field.set(student,"张三");
//取值 get方法
field.get(student);
System.out.println(field.get(student));//输出:张三

注:(总结)
1、获取指定的变量------如果是public修饰的变量getField(“方法名”) 、如果是非public修饰的用 类对象.getDeclareField(“name”)
2、创建对象 ------为什么要创建对象??—>因为获取的类信息来源于第二阶段(对象阶段),但是要使用变量需要进入第三阶段,创建对象,给变量内存空间才能进行调用
3、如果是privated修饰的变量需要暴力反射 获取的变量类信息.setAccessible(true)
4、赋值:变量信息.set(对象,值)
5、取值:变量信息.get(对象)

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...