【Java】基础——反射(Reflection)基础

2024-02-24 17:12
文章标签 java 基础 反射 reflection

本文主要是介绍【Java】基础——反射(Reflection)基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. 反射概述

引言

1.1 反射是什么?

1.2 反射提供的功能

1.3 反射的作用

2. 获取类的信息

2.1 获取反射中的Class对象

2.2 通过反射创建类对象

2.3 通过反射获取类的成员变量

2.4 通过反射获取类的方法


1. 反射概述

引言

本篇对反射基础进行了讲解。

可以带着以下问题进行学习:

  • 什么是Java语言的反射机制?
  • 反射都提供了什么功能?
  • 反射有什么作用?
  • 反射如何获取Class对象?
  • 反射如何创建类对象?
  • 反射如何获取类的成员变量和类的成员方法?

1.1 反射是什么?

Java语言的反射机制: 在Java中,运行状态时,只要给定类的名字,就能知道这个类的所有信息,可以构造出指定对象,可以调用它的任意一个属性和方法。这种动态获取信息以及动态调用对象的方法的功能是Java语言的反射机制。

一般,我们使用某个类时一定知道这个类是什么类,有什么作用,对这个类进行实例化,使用这个类对象进行操作。

反射则是在一开始并不知道我们要初始化的类对象是什么,自然无法new出对象,这时候需要进行反射调用。

反射允许对封装类的字段、方法和构造函数的信息进行编程访问。

1.2 反射提供的功能

Java反射机制主要提供以下功能:

  1.     在运行时判断任意一个对象所属的类。

  2.     在运行时构造任意一个类的对象。

  3.     在运行时判断任意一个类所具有的成员变量和方法。

  4.     在运行时调用任意一个对象的方法。     

1.3 反射的作用

反射的作用:

  • 动态的加载类,动态获取类的信息(属性、方法、构造器)

  • 动态的构造对象

  • 动态调用类和对象的任意方法、构造器

  • 获取泛型信息

  • 处理注解

  • 动态代理

  • ...

2. 获取类的信息

2.1 获取反射中的Class对象

反射始于Class,Class是一个类,是一个用来描述类的类,封装了当前对象所对应类的信息。对于每个类,JRE都为其保留一个不变的Class类型的对象。一个类在JVM中只会有一个Class实例。

获取Class类对象三种方法:

  1. Class.forNam(全类名) 静态方法。源代码阶段(.java -> .class)
  2. 类名.class() 方法(基本类型只可该方法获得Class对象)。加载阶段(.class加载到内存中)
  3. 对象.getClass() 方法。运行阶段(内存中运行 A a = new A();)

三种方法实现代码如下:

 

 

//第一种,使用 Class.forName 静态方法。
Class clazz1 = Class.forName("reflect.Person");
//第二种,使用 .class 方法。
Class clazz2 = Person.class;
//第三种,使用类对象的 getClass() 方法。
Person person =  new Person("浅浅",18);
Class clazz3 = person.getClass();

判断是否为某个类的实例

一般,使用instanceof关键字来判断是否为某个类的实例:

public native boolean isInstance(Object obj);

 

也可以使用反射中Class对象的isInstance()方法来判断是否为某个类的实例:

public boolean isAssignableFrom(Class<?> cls)

2.2 通过反射创建类对象

主要两种方式:

1.通过 Class对象的newInstance() 方法(只能使用默认的无参数构造方法)。

2.通过 Constructor对象的newInstance() 方法(可以选择特定构造方法)。

其实, class.newInstance() 内部实现也是通过 Constructor。而且现在已经标记为 @Deprecated(since="9"),建议使用 Constructor 。

//获取class对象
Class clazz = Class.forName("reflect.Person");//如果有默认构造方法,就使用这个,先通过Class对象获取指定的Constructor对象
Person p1 = (Person) clazz.getConstructor().newInstance();
//指定构造方法
Person p2 = (Person) clazz.getDeclaredConstructor(String.class, int.class).newInstance("dr", 1);

2.3 通过反射获取类的成员变量

获取成员变量的两个方法:

  1. Field getField(String name): 获得命名的公共字段,只能获取 public 修饰的变量,如果是私有变量,会报错NoSuchField。
  2. Field[] getFields(): 获得类的所有公共字段。
  3. Field getDeclaredField(String name): 获得类声明的字段,在不知道变量的权限修饰符的时候,建议使用, 比较保险。
  4. Field[] getDeclaredFields(): 获得类声明的所有字段。

修改变量的值的两类方法:

  1. 引用类型:只有一个方法 set(Object obj, Object value)
  2. 基本类型:为每个基本类型,都提供了一个方法,例如 setInt(Object obj, int i)setLong(Object obj, long l) 大家使用时,根据不同的类型,选择不同的方法。

注:若修改的属性为私有属性,则需要先设置field.setAccessible(true),设置之后才 可以修改值。

//获取class对象
Class clazz = Class.forName("reflect.Person");
//构造对象
Person p = (Person) clazz.getDeclaredConstructor(String.class, int.class).newInstance("dr", 18);
//获取指定变量 name
Field nameField = clazz.getField("name");
//修改变量的值
nameField.set(p,"张三");
//获取指定变量 age 
Field ageField = clazz.getDeclaredField("age");
//age 是private变量,需要先设置可用
ageField.setAccessible(true);
//修改变量的值
ageField.setInt(p,17);

 

2.4 通过反射获取类的方法

获取类方法的两个方法:

  1. Method getMethod(String name, Class[] params): 使用特定的参数类型,获得命名的公共方法。
  2. Method[] getMethods(): 获得类的所有公共方法。
  3. Method getDeclaredMethod(String name, Class[] params): 使用特写的参数类型,获得类声明的命名的方法。
  4. Method[] getDeclaredMethods(): 获得类声明的所有方法。
//获取class对象
Class clazz = Class.forName("reflect.Person");
//构造对象
Person p = (Person) clazz.getDeclaredConstructor(String.class, int.class).newInstance("dr", 18);
//获取指定方法 "addFavorite"
Method method = clazz.getMethod("addFavorite", String.class);
//调用对象方法
method.invoke(p, "篮球");
//获取指定方法 "changeAge"
Method privateMethod = clazz.getDeclaredMethod("changeAge", int.class);
//changeAge 是private方法,需要先设置可用
privateMethod.setAccessible(true);
privateMethod.invoke(p, 17);

注:当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。

public Object invoke(Object obj, Object... args)

 

 

这篇关于【Java】基础——反射(Reflection)基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/742767

相关文章

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过