首页 > 编程语言 >Java的反射机制

Java的反射机制

时间:2023-10-08 15:11:52浏览次数:34  
标签:反射 Java 对象 Method Employee 机制 方法 Class

Java的反射机制

前言

能够分析类能力的程序称为反射,反射机制可以用来:

  • 在运行程序时分析类的能力;
  • 在运行时检查对象;
  • 实现泛型数组操作代码;
  • 利用Method对象;

Class类

在程序运行期间,Java运行时系统始终为所有对象维护一个「运行时类型信息标识」。

这个信息会跟踪每个对象所属的类,Java虚拟机利用运行时类型信息标识选择要执行的正确的方法。

保存这些信息的类名为Class,可以使用这个特殊的Java类访问这些信息。

虚拟机为每个类型管理一个唯一的Class对象,可以利用「==」运算符比较两个Class对象的类型。

可以通过Object类中的getClass()方法返回一个Class类的实例。

String str = new String();
Class strClass = str.getClass();

可以使用Class类型中的forName()静态方法,通过指定类的全限定类名获取该指定类的Class实例。

String className = "java.util.Random";
Class randomClass = Class.forName(className);

可以使用「类型.class」的方式获取类型的Class实例。

Class randomClass = Random.class;
Class intClass = int.class;
Class doubleArrClass = Doublue[].class;

Class类实际上是一个泛类型。(例如:String.class的类型是Class

可以通过Class对象的getConstructor方法得到一个Constructor类型的对象,然后使用该对象的newInstance方法来构造一个实例。(要求必须存在一个无参构造方法)

Class strClass = String.class;
Constructor strConstructor = strClass.getConstructor();
String str = strConstructor.newInstance();

资源

类通常有一些关联的数据文件,在Java中,这些文件被称为「资源」。

Class类提供了一个有用的服务,可以用来查找资源文件:

  1. 获得拥有资源的类的Class实例;
  2. Class实例的getResource("文件名"),可以获取资源的URL位置;
  3. Class实例的getResourceAsStream方法得到一个输入流来读取文件中的数据;

文件的自动装载是利用资源加载特性完成的。

利用反射分析类的能力

在java.lang.reflect包中,有三个类Filed、Method和Constructor分别描述类的字段、方法和构造器:

  • 这三个类都有一个叫作getName的方法,用来放回字段、方法和构造器的名称;

  • 这三个类都有一个叫作getModifiers的方法,返回一个整数,描述使用的访问权限修饰符;

  • java.lang.reflect包中的Modifier类,该类中的静态方法可以用来分析getModifiers方法的返回值;

  • Filed类有一个getType方法,用来返回描述字段类型的Class对象;

  • Class类中的getFields、getMethods和getConstructors方法将分别返回这个类支持的「公共字段」、「公共方法」和「公共构造器」的数组,包括其超类的公共成员;

  • Class类的getDeclareFields、getDeclareMethods和getDeclareConstructors方法将分别返回类中声明的全部字段、方法和构造器的数组,但是不包括超类的成员;

  • Class类的getPackageName方法可以获取这个类所在的包名;

使用反射在运行时分析对象

利用反射机制可以查看在编译时还不知道的对象字段。

Field类中的get(obj)方法可以获得obj对象当前字段的值。

// Employee(name,age)
Employee employee = new Employee("Jack",25);
Class emplClass = employee.getClass();
Field nameFiled = emplClass.getField("name");
Object nameObject = nameFiled.get(employee);

Filed类中的set(obj,value)可以给obj对象当前字段的值设置为value。

// Employee(name,age)
Employee employee = new Employee("Jack",25);
Class emplClass = employee.getClass();
Field nameFiled = emplClass.getField("name");
nameFiled.set(employee,"ZhangSan");

只能对公共成员字段使用get和set方法,否则会跑出IllegalAccessException异常。

Java的安全机制允许查看一个对象有哪些字段,但是除非拥有访问权限,否则将不允许读写那些字段的值。

反射机制的默认行为受限于Java的访问控制,可以调用Filed、Method和Constructor对象的setAccessible方法覆盖Java的访问控制。

// Employee(name,age)
Employee employee = new Employee("Jack",25);
Class emplClass = employee.getClass();
Field nameFiled = emplClass.getField("name");
// 覆盖这个字段的访问权限
nameField.setAccessible(Boolean.TRUE);
// 可以正常访问name这个私有成员字段
Object nameObject = nameFiled.get(employee);

调用任意方法和构造器

利用Method类中的invoke方法,可以调用包装在当前Method对象中的方法:

  • invoke方法的签名是:Object invoke(Object, Object... args)
  • 第一个参数是隐式参数,其余的对象提供了显式参数
  • 对于静态方法,第一个参数可以忽略,即可以设置为null
// void doSomething(String,Integer)
Method doSomeThingMethod = classObject.getMethod("doSomething");
doSomeThingMethod.invoke("some thing",12);

可以通过调用Class对象的getDeclareMethods方法获得Method对象组。

Method[] methodArray = classObject.getDeclareMethods();

可以通过调用Class对象的getMethod方法获得指定的Method对象。

getMethod方法的签名是:Method getMethod(String name, Class... parameterTypes)

Method method = classObject.getMethod("getName");

可以使用类似的方法调用任意的构造器,需要将构造器的参数类型提供给Class.getConstructor方法,并把参数值提供给Constructor.newInstance方法。

Constructor constructor = classObject.getConstructor(Long.class);
Object obj = constructor.newInstance(20L);

标签:反射,Java,对象,Method,Employee,机制,方法,Class
From: https://www.cnblogs.com/myblog20231005/p/17749115.html

相关文章

  • java代码注释和空行删除,软著源码
    notepad++替换,结合正则表达式处理匹配//单行注释//.*匹配/**多行注释*/注意需要非贪婪模式,所以有一个?使用/\*{2}[\s\S]*?\*/匹配空行^\s*\n上面多行注释的匹配,需要非贪婪模式如果没有那个问号,将会把这一整块都匹配进去,第一块多行注释的头/**和最后一个多行注释......
  • mybatis出现错误 java lang NumberFormatException:For input string:A1
    使用mybatis,当使用map传参并且在iftest判断时使用map中所传的参数时,可能会产生如题的报错,具体报错信息见下图:分析这个错误,自己调试也找过度娘,“坚信”自己代码并没问题,但是问题始终无法解决。最后在一个帖子看到说iftest判断时,传入的参数跟匹配的值类型必须一致,于是调整了自己代......
  • JavaScript实现大文件分片上传处理
    我可以为你讲解如何实现JavaScript实现大文件分片上传处理,以下是具体的攻略步骤:步骤1:选择文件在实现大文件分片上传之前,第一步需要让用户选择一个文件。你可以在页面上加入一个文件选择表单,如下所示:<inputtype="file"name="file"id="file">步骤2:对文件进行分片处理当用户......
  • Java 队列Queue的一些基本操作与概念!!!!!!!!
    首先Java中的队列(Queue)是一种先进先出的数据结构。其中常见的一些基本操作与方法,包括:1、创建队列对象。例如:ArrayDeque、LinkedList等。2、入队操作。将元素添加到队列的末尾处,使用offer()方法。3、出队操作。从队列的头部移除并返回元素,使用poll()方法。......
  • ChatGPT 问答00023 java代码发邮件怎么带附件
    在Java中发送带附件的Email,可以使用JavaMail和JAF(JavaBeansActivationFramework)库来实现。以下是一个基本的示例代码,演示如何发送带有附件的Email:importjava.util.*;importjavax.mail.*;importjavax.mail.internet.*;publicclassSendEmailWithAttachment{public......
  • Java 位运算的解读 & | ^ ~ << >>
    Java中的位运算包括以下几种:按位与(&):对应位上,如果两个数都是1,则结果为1,否则为0。inta=3;//二进制0011intb=5;//二进制0101//0001=1System.out.println("a&b="+(a&b));按位或(|):对应位上,如果两......
  • 94基于java的智能物流管理系统设计与实现(含配套lun文,可参考做毕设)
    本章节给大家带来一个基于java智能物流管理系统设计与实现,可适用于校园物流管理系统,物流配送系统,快递物流管理,物流追踪系统,物流系统,物流运输系统,javaweb物流系统,springboot物流管理系统,javaweb智能物流系统等等;项目背景随着互联网技术的快速发展,网络时代的到来,网络信息也将会......
  • 94基于java的智能物流管理系统设计与实现(含配套lun文,可参考做bi设)
    本章节给大家带来一个基于java智能物流管理系统设计与实现,可适用于校园物流管理系统,物流配送系统,快递物流管理,物流追踪系统,物流系统,物流运输系统,javaweb物流系统,springboot物流管理系统,javaweb智能物流系统等等;项目背景随着互联网技术的快速发展,网络时代的到来,网络信息也将会......
  • Maven 引用CDH 5.4 的zookeeper时报错:Could not find artifact javax.jms:jms:jar:1.1
    错误:Couldnotfindartifactjavax.jms:jms:jar:1.1incloudera由于默认5.4.0的包引用了zookeeper3.3.1版本,进而引用了log4j的某个版本,导致的报错,改为如下即可: pom:使用cloudera的源:<repositories><repository><id>cloudera</id><u......
  • JAVA工作日志
    你好我好大家好,今天带大家一起完成工作日志这个模块,每天努力一点点,将来成就一大步。首先我们先来完成提交统计这一块,从图中可以看出来我们需要日志的类型和统计值,统计值又包括应提交数和已提交数。我们来定义一个类用来展示。 编写逻辑代码,注意红色字体提醒!!! 这个时候我们......