java中反射知识点概念

这里写自定义目录标题

  • 1.什么是反射--动态注入?
  • 2.反射的诞生背景
  • 3.反射的意义
  • 4.反射后可以做些什么
  • 5.反射相关的主要API
  • 6.反射的优缺点
  • 7.反射和不反射基础使用
  • 8.工厂模式使用反射
    • 8.1首先我们来看看不使用反射的情况:
    • 8.2使用反射的情况:
  • 9.Java中使用工厂模式反射
  • 10.springboot项目中依赖注入和反射
  • 11.进行依赖注入时,使用了反射机制
  • 12.反射机制可以理解为是在运行时获取的类信息的一种机制

1.什么是反射–动态注入?

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在运行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
在这里插入图片描述

2.反射的诞生背景

Java程序中,所有的对象都有两种类型:编译时类型运行时类型,而很多时候对象的编译时类型和运行时类型不一致。 Object obj = new String(“hello”); obj.getClass()

例如:某些变量或形参的声明类型是Object类型,但是程序却需要调用该对象运行时类型的方法,该方法不是Object中的方法,那么如何解决呢?

解决这个问题,有两种方案:

方案1:在编译和运行时都完全知道类型的具体信息,在这种情况下,我们可以直接先使用instanceof运算符进行判断,再利用强制类型转换符将其转换成运行时类型的变量即可。

方案2:编译时根本无法预知该对象和类的真实信息,程序只能依靠运行时信息来发现该对象和类的真实信息,这就必须使用反射。

3.反射的意义

使用反射机制的好处是增加了程序的灵活性和扩展性

4.反射后可以做些什么

Java反射机制提供的功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

5.反射相关的主要API

java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器

6.反射的优缺点

优点:

  • 提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力

  • 允许程序创建和控制任何类的对象,无需提前硬编码目标类

缺点:

  • 反射的性能较低

    • 反射机制主要应用在对灵活性和扩展性要求很高的系统框架上
  • 反射会模糊程序内部逻辑,可读性较差

7.反射和不反射基础使用

1.创建类

// 不使用反射
MyClass obj = new MyClass();// 使用反射
Class<?> clazz = Class.forName("com.example.MyClass");
Object obj = clazz.newInstance();

使用反射机制的好处是增加了程序的灵活性和扩展性,以下是一些使用反射的优点:

  1. 运行时动态加载类:通过反射机制,可以在运行时动态地加载不同的类,实现插件化和动态扩展功能。例如,一个框架可以根据配置文件中指定的类名动态加载对应的实现类。
// 不使用反射
MyClass obj = new MyClass();// 使用反射
Class<?> clazz = Class.forName("com.example.MyClass");
Object obj = clazz.newInstance();
  1. 创建对象灵活:通过反射机制,可以在运行时动态地创建对象,而无需在代码中显式地引用类。这对于需要根据条件创建不同对象的场景非常有用。
// 不使用反射
MyClass obj;
if (condition) {obj = new MyClassA();
} else {obj = new MyClassB();
}// 使用反射
Class<?> clazz;
if (condition) {clazz = Class.forName("com.example.MyClassA");
} else {clazz = Class.forName("com.example.MyClassB");
}
Object obj = clazz.newInstance();
  1. 可以在运行时获取类的信息:通过反射机制,可以在运行时获取一个类的名称、父类、构造方法、成员变量、方法等信息,实现灵活的编程逻辑。
Class<?> clazz = MyClass.class;
String className = clazz.getName();
Class<?> superClass = clazz.getSuperclass();
Constructor<?>[] constructors = clazz.getConstructors();
Field[] fields = clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
  1. 动态调用方法和访问属性:通过反射机制,可以在运行时动态地调用一个对象的方法,并传递相应的参数,或者在运行时动态地访问一个对象的属性,以便读取或修改相应的值。这对于一些通用的处理逻辑非常有用,比如序列化、反序列化、ORM框架等。
Object obj = new MyClass();
Method method = obj.getClass().getMethod("methodName", String.class);
method.invoke(obj, "parameterValue");Field field = obj.getClass().getDeclaredField("fieldName");
field.setAccessible(true);
field.set(obj, "fieldValue");

如果不使用反射,我们将无法在运行时动态地加载类、创建对象、调用方法和访问属性。这将限制程序的灵活性和扩展性,并导致代码的冗余和重复。

总而言之,反射机制使得我们可以在运行时动态地操作和探知类的信息,从而增加了程序的灵活性和可扩展性。但是,反射也会带来一定的性能开销,并且会导致代码的可读性降低,因此在使用反射时需要谨慎权衡。

8.工厂模式使用反射

举一个更具体的例子来体会使用反射的好处。
假设我们有一个简单的工厂类,根据传入的类名动态创建对应类的实例。

8.1首先我们来看看不使用反射的情况:

public class SimpleFactory {public static Object createInstance(String className) {if ("A".equals(className)) {return new A();} else if ("B".equals(className)) {return new B();}// 可能还会有其他类的创建判断return null;}
}

在上述代码中,如果我们要添加新的类,就需要修改工厂类的代码,这违反了开闭原则。而使用反射可以让工厂类更加灵活,不需要每次添加新的类都修改工厂类的代码。

8.2使用反射的情况:

创建反射工厂

public class ReflectiveFactory {public static Object createInstance(String className) {try {Class<?> clazz = Class.forName(className);return clazz.newInstance();} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {ex.printStackTrace();return null;}}
}

通过使用反射,我们可以根据传入的类名动态地加载并创建对应类的实例,而无需明确地引用类名。这样一来,当有新的类需要添加时,只需要提供对应的类名,而不需要修改工厂类的代码。

假设我们有类A和类B:

public class A {public void doSomething() {System.out.println("A is doing something");}
}public class B {public void doSomething() {System.out.println("B is doing something");}
}

然后我们使用ReflectiveFactory来创建这两个类的实例:

public class Main {public static void main(String[] args) {A a = (A) ReflectiveFactory.createInstance("A");B b = (B) ReflectiveFactory.createInstance("B");a.doSomething();b.doSomething();}
}

在这个例子中,如果我们要添加一个新的类C,只需要提供C的类名,比如"com.example.C",而不需要修改ReflectiveFactory类的代码。

总之,使用反射能够使程序更加灵活,减少了硬编码,提高了扩展性和可维护性。希望这个例子能够帮助您更好地理解使用反射的好处。

9.Java中使用工厂模式反射

当在Java中使用工厂模式时,结合反射可以使得代码更加灵活,以下是一个简单的示例:

假设我们有一个接口 Animal 和它的两个实现类 DogCat,现在我们想要创建一个动物的工厂来根据不同的需求生产相应的动物实例。我们可以利用反射来实现这一功能。

首先是接口及其实现类的定义:

// Animal 接口
public interface Animal {void makeSound();
}// Dog 类实现了 Animal 接口
public class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("汪汪汪");}
}// Cat 类实现了 Animal 接口
public class Cat implements Animal {@Overridepublic void makeSound() {System.out.println("喵喵喵");
}

然后是动物工厂类的定义,利用反射根据传入的类名动态创建对应的实例:

public class AnimalFactory {public static Animal createAnimal(String animalType) {Animal animal = null;try {// 使用反射根据类名创建实例Class<?> clazz = Class.forName(animalType);animal = (Animal) clazz.getDeclaredConstructor().newInstance();} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();}return animal;}
}

最后是使用工厂创建动物实例的示例:

public class Main {public static void main(String[] args) {Animal dog = AnimalFactory.createAnimal("com.example.Dog");Animal cat = AnimalFactory.createAnimal("com.example.Cat");dog.makeSound();  // 输出:汪汪汪cat.makeSound();  // 输出:喵喵喵}
}

在这个示例中,动物工厂类 AnimalFactory 使用了反射机制根据传入的类名动态创建对应的实例,这样我们就不需要在工厂类中硬编码各个动物类的实例化过程,使得工厂类更加灵活和可扩展。

10.springboot项目中依赖注入和反射

当涉及到依赖注入和反射时,Spring Boot提供了强大的支持。下面是一个简单的Java代码示例,演示了在Spring Boot中如何使用依赖注入和反射。

首先,我们假设有一个接口 UserService 和它的两个实现类 UserServiceImpl1UserServiceImpl2

public interface UserService {void getUserInfo();
}@Component // 声明为Spring组件,使其能够被注入--使用反射动态注入
public class UserServiceImpl1 implements UserService {@Overridepublic void getUserInfo() {System.out.println("UserServiceImpl1: Getting user information...");}
}@Component // 声明为Spring组件,使其能够被注入--使用反射动态注入
public class UserServiceImpl2 implements UserService {@Overridepublic void getUserInfo() {System.out.println("UserServiceImpl2: Getting user information...");}
}

接下来,我们创建一个使用依赖注入和反射的类 UserController

@RestController
public class UserController {private final UserService userService;public UserController(UserService userService) {this.userService = userService;}@GetMapping("/user")public void getUser() {userService.getUserInfo();}
}

在上述代码中,UserController 类使用构造函数注入 UserService 接口的实例。通过使用 @RestController 注解,Spring Boot 将会自动创建该类的实例,并将 UserService 的实例作为参数传入构造函数。

最后,我们需要在启动类中设置 Spring Boot 应用程序。

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在上述代码中,@SpringBootApplication 注解表示这是一个 Spring Boot 应用程序的启动类。

当我们运行这个应用程序时,Spring Boot 将会自动扫描 UserControllerUserService 的实现类,并通过依赖注入将 UserServiceImpl1 或者 UserServiceImpl2 的实例传递给 UserController。然后,当访问 /user 路径时,UserController 调用 userService.getUserInfo() 方法,输出相应的信息。

这个示例展示了在Spring Boot中使用依赖注入和反射的基本原理。通过依赖注入,我们可以轻松地将实现类注入到需要它们的类中,而无需显式地创建它们的实例。同时,反射机制使得Spring Boot能够动态地实例化对象并完成依赖注入。

11.进行依赖注入时,使用了反射机制

Spring Boot 在进行依赖注入时,使用了反射机制。通常情况下,我们不需要显式地使用反射来实现依赖注入,而是让 Spring Boot 自动完成这个过程。

当我们给一个类添加 @Component 注解时,它就成为了一个 Spring 组件,并且可以被注入到其他需要它的类中。在启动应用程序时,Spring Boot 会扫描所有的组件,然后使用反射机制来实例化它们。在实例化过程中,Spring Boot 也会检查组件之间的依赖关系,并自动完成依赖注入。

具体来说,在上面的示例中,UserController 类的构造函数需要一个 UserService 实例。当 Spring Boot 实例化 UserController 类时,它会检查 UserService 接口有哪些实现类,并选择一个与 UserController 类进行依赖注入。这个过程中,Spring Boot 使用了反射机制来实例化 UserService 实现类的对象,并将其传递给 UserController 的构造函数。

总之,在 Spring Boot 中,我们可以通过添加注解来声明组件,并让 Spring Boot 自动完成依赖注入的过程。在这个过程中,Spring Boot 使用反射机制来实例化对象和完成依赖注入。

12.反射机制可以理解为是在运行时获取的类信息的一种机制

反射机制可以理解为在运行时获取类的信息并进行操作的一种机制。在 Java 中,通过反射机制,可以在程序运行时动态地获取、检查和修改类、对象、方法、字段等的信息,以及调用类的方法和构造函数。

使用反射机制,可以实现以下功能:

  1. 获取类的信息:可以获取类的名称、修饰符、父类、实现的接口等信息。

  2. 创建对象:可以通过反射机制创建类的对象,包括调用无参构造函数或有参构造函数来实例化对象。

  3. 调用方法和访问字段:可以通过反射机制调用类的方法和访问类的字段,包括公共方法和字段、私有方法和字段。

  4. 动态代理:通过反射机制可以生成代理对象,用于在运行时动态地处理对目标对象的方法调用。

  5. 获取泛型信息:可以通过反射机制获取类、方法、字段等的泛型信息,包括参数化类型、泛型方法等。

反射机制提供了一种强大的能力,可以在编写代码时不需要提前知道类的具体信息,而是在运行时动态地获取和操作类的信息。但同时,反射机制也会带来一些性能上的开销,因此在使用反射时需要权衡其灵活性和性能消耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/185591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cesium.CustomShader颜色值显示错误

官方示例&#xff1a; Cesium Sandcastle 测试过程&#xff1a; 1、修改示例&#xff0c;把customshader中的fragmentShaderText替换为如下代码 void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {//注意&#xff1a;下述颜色的b值是0.1&#x…

智能配电箱监控系统

智能配电箱监控系统是一种用于实时监控配电箱运行状态和电能质量的系统。它通过集成应用物联网技术&#xff0c;实现对配电箱的数据采集、整合和处理&#xff0c;从而让工作人员能够远程了解和掌握配电箱的情况。通过电力设备的数字化&#xff0c;依托电易云-智慧电力物联网&am…

数字孪生3D场景开发工具:弥补不足,开拓全新可能

随着数字化时代的来临&#xff0c;越来越多的企业和行业开始探索数字孪生技术的应用。数字孪生是指通过数字技术将现实世界中的物体、场景等复制到虚拟世界中&#xff0c;以实现实时监测、预测和优化。然而&#xff0c;在数字孪生的发展过程中&#xff0c;一些不足也逐渐浮现。…

如何去选择合适的线缆测试仪?CAT8网线认证测试

如何去选择合适的线缆测试仪? 如果你是第三方检测单位&#xff0c;系统集成商&#xff0c;或者线缆生产厂家&#xff0c;我个人建议选择福禄克DSX系列无疑是比较保险的做法&#xff0c;因为考虑到福禄克在国内耕耘多年所积累起来的品牌知名度和口碑&#xff0c;选择一款大家都…

PHP程序员必备技能:OSS云存储实现教程!

近些年来&#xff0c;云存储的应用越来越广泛&#xff0c;阿里云的OSS云存储服务也在国内市场中占据了一席之地。在此基础上&#xff0c;本文将分享如何使用PHP实现OSS云存储。 首先&#xff0c;我们需要在阿里云官网上注册一个账号并创建一个OSS存储空间。创建步骤在官方文档…

振南技术干货集:各大平台串口调试软件大赏(4)

注解目录 &#xff08;串口的重要性不言而喻。为什么很多平台把串口称为 tty&#xff0c;比如 Linux、MacOS 等等&#xff0c;振南告诉你。&#xff09; 1、各平台上的串口调试软件 1.1Windows 1.1.1 STCISP &#xff08;感谢 STC 姚老板设计出 STCISP 这个软件。&#xf…

相机标定张正友、opencv和halcon对比(1)

本文将从基本标定开始&#xff0c;结合实际工作经验&#xff0c;分析张正友、opencv和halcon三者相机标定的深层原理与不同之处&#xff0c;内容比较多&#xff0c;如果出现错误请指正。 相机光学模型 我们使用的镜头都是由多组镜片组成&#xff0c;它实际上是一种厚透镜模型…

羊大师提问,为什么吃得越咸越容易出现健康问题?

羊大师提问&#xff0c;为什么吃得越咸越容易出现健康问题&#xff1f; 在现代社会中&#xff0c;有一种追求咸味食物的趋势&#xff0c;许多人都钟爱于吃咸味食物。吃咸味食物往往容易导致健康问题&#xff0c;引发各种疾病。那么为什么吃的越咸越容易生病呢&#xff1f; 今…

C++二分查找算法:132 模式枚举3

说明 本篇是视频课程的讲义&#xff0c;可以看直接查看视频。也可以下载源码&#xff0c;包括空源码。 本文涉及的基础知识点 二分查找算法合集 本题不同解法 包括题目及代码C二分查找算法&#xff1a;132 模式解法一枚举3C二分查找算法&#xff1a;132 模式解法二枚举2代码…

黑洞:宇宙中最神秘的天体

黑洞&#xff1a;宇宙中最神秘的天体 一、引言 在浩瀚的宇宙中&#xff0c;有一种神秘的天体&#xff0c;它强大到连光也无法逃逸&#xff0c;这就是黑洞。自从黑洞理论被提出以来&#xff0c;它一直是物理学家和天文学家研究的焦点。尽管我们还无法直接看到黑洞&#xff0c;…

使用 Redis Zset 有序集合实现排行榜功能(SpringBoot环境)

目录 一、前言二、Redis Zset 的基本操作三、通过Redis 命令模拟排行榜功能3.1、排行榜生成3.2、排行榜查询 四、SpringBoot 使用 Redis Zset 有序集合实现排行榜功能 一、前言 排行榜功能是非常常见的需求&#xff0c;例如商品售卖排行榜单、游戏中的积分排行榜、配送员完单排…

VirtualBox上安装CentOS7

基础环境&#xff1a;宿主机是64位Windows10操作系统&#xff0c;通过无线网访问网络。 macOS可以以类似方式进行安装&#xff0c;不同之处见最后补充。 Step1 安装VirtualBox VirtualBox是一款免费、开源、高性能的虚拟机软件&#xff0c;可以跨平台运行&#xff0c;支持Wi…

【神印王座】永恒之塔秘密透露,林鑫告白李馨,皓晨采儿甜蜜接吻

Hello,小伙伴们&#xff0c;我是拾荒君。 《神印王座》第83集如期而至&#xff0c;带来了令人期待已久的更新。与众多热情的观众一样&#xff0c;拾荒君一得到更新消息&#xff0c;便急不可耐地观赏起来。这一集中&#xff0c;龙皓晨随着月魔宫的月夜商队成功抵达联盟&#xf…

C++: string的模拟实现

C: string的模拟实现 一.前置说明1.模拟实现string容器的目的2.我们要实现的大致框架 二.默认成员函数1.构造函数2.拷贝构造函数1.传统写法2.现代写法 3.析构函数4.赋值运算符重载1.传统写法2.现代写法 三.遍历和访问1.operator[]运算符重载2.iterator迭代器 四.容量相关函数1.…

ssm+vue的公司安全生产考试系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的公司安全生产考试系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

探索前端设计的新境界——介绍IVueUI工具助力Vue页面设计

在快速发展的前端领域&#xff0c;Vue.js作为一款渐进式JavaScript框架&#xff0c;一直备受开发者喜爱。然而&#xff0c;在Vue前端开发的旅程中&#xff0c;页面设计常常是一个不可避免的挑战。今天&#xff0c;我要向大家介绍一款令Vue前端开发者受益匪浅的工具——www.ivue…

Python文件操作

目录 一.文件的编码二.文件的读取三.文件的写入四.文件的追加五.文件操作综合案例 一.文件的编码 编码就是一种规则集合&#xff0c;记录了内容和二进制进行相互转换的逻辑。最常见的是UTF-8编码计算机只认识0和1&#xff0c;所以需要将内容翻译成0和1才能保存在计算机中。同时…

“大+小模型”赋能油气行业高质量发展

近日&#xff0c;中国石油石化科技创新大会暨新技术成果展在北京盛大举行&#xff0c;九章云极DataCanvas公司携油气行业一站式AI综合解决方案重磅亮相&#xff0c;充分展示了公司助推油气行业实现AI规模化应用深厚的AI技术实力和领先的AI应用水准&#xff0c;赢得了行业专家和…

spring boot整合Jasypt实现配置加密

文章目录 目录 文章目录 前言 一、Jasypt是什么&#xff1f; 二、使用步骤 1.引入 2.测试使用 3.结果 总结 前言 一、Jasypt是什么&#xff1f; Jasypt&#xff08;Java Simplified Encryption&#xff09;是一个Java库&#xff0c;提供了一种简单的加密解密方式&#xff0c…

热门话题解析:pytest测试用例顺序问题解决方案!

前言 上一篇文章我们讲了在pytest中测试用例的命名规则&#xff0c;那么在pytest中又是以怎样的顺序执行测试用例的呢&#xff1f; 在unittest框架中&#xff0c;默认按照ACSII码的顺序加载测试用例并执行&#xff0c;顺序为&#xff1a;09、AZ、a~z&#xff0c;测试目录、测…