java中反射知识点概念

news2024/11/27 11:31:37

这里写自定义目录标题

  • 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 {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

// Cat 类实现了 Animal 接口
public class Cat implements Animal {
    @Override
    public 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 {
    @Override
    public void getUserInfo() {
        System.out.println("UserServiceImpl1: Getting user information...");
    }
}

@Component // 声明为Spring组件,使其能够被注入--使用反射动态注入
public class UserServiceImpl2 implements UserService {
    @Override
    public 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.coloradmin.cn/o/1267074.html

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

相关文章

【springboot】idea项目启动端口被占用

问题 idea本地启动springboot项目端口老是被占用 解决 关闭被占用的端口进程 步骤: 1. winR打开程序框 2. 查出被占用端口的进程id netstat -ano | finderstr 端口号 例如 netstat -ano | finderstr 81013.杀死进程 taskkill /pid 进程id -t -f 例如 taskkill /pid 2…

1688 API接口的介绍丨商品详情页接口丨搜索商品列表接口

1688&#xff0c;作为中国领先的B2B电子商务平台&#xff0c;为全球的买家和卖家提供了一站式的采购和销售服务。而它的API接口&#xff0c;更是开放了1688平台的核心功能&#xff0c;让开发者能够根据自己的需求来定制和扩展商业应用。 1688 API接口的介绍 1688 API接口提供…

使用影刀指令+python实现简单的长文本乱序加密

本文意在利用影刀指令python代码&#xff0c;实现一种较为简单的长文本加密和解密&#xff0c;流程结构分为两步&#xff1a; 加密原理–是把字符转为列表&#xff0c;利用列表random模块中的shuffle函数做随机乱序。解密原理–是利用了列表的索引追踪&#xff0c;先前创建字典…

Vue3-目录调整

默认生成的目录结构不满足我们的开发需求&#xff0c;所以这里需要做一些自定义改动。 主要是以下工作&#xff1a; 1.删除一些初始化的默认文件 2.修改剩余代码内容 3.新增调整我们需要的目录结构 在src文件夹下创建两个新文件夹&#xff0c;一个叫api&#xff08;请求模…

re:Invent 2023:PingCAP 荣获亚马逊云科技 2023 年度合作伙伴奖项

2023 年 11 月 27 日 – 12 月 1 日&#xff0c; 2023 亚马逊云科技 re:Invent 在拉斯维加斯举办&#xff0c;亚马逊云科技合作伙伴奖项在合作伙伴颁奖晚会上颁布&#xff0c; PingCAP 荣获亚马逊云科技大中华区 “2023 年度 ISV 合作伙伴” 和 “2023 年度亚马逊云科技 Market…

dockerfile文件:copy和add 异同

相同点&#xff1a; 复制文件或目录&#xff1a; 无论是 COPY 还是 ADD 都可以将文件或目录从构建上下文复制到容器中。支持源路径和目标路径&#xff1a; 两者都需要指定源路径和目标路径&#xff0c;用于指定要复制的文件或目录在主机上的位置以及在容器中的目标路径。 不同…

Re0: 从零实现一个置顶任意窗口的小工具

前言 话不多说&#xff0c;先上效果&#xff1a; 这里展示的是通过下拉框选择窗口&#xff0c;让窗口显示并置顶&#xff0c;其实还可以直接通过快捷键&#xff08;先鼠标点击要置顶的窗口&#xff0c;再使用CTRLSHIFTT&#xff09;&#xff0c;本文涉及到的完整代码已上传到G…

【开源】基于Vue+SpringBoot的智能教学资源库系统

项目编号&#xff1a; S 050 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S050&#xff0c;文末获取源码。} 项目编号&#xff1a;S050&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课…

现代风客餐阳台开放式一体布局,设计亮点。福州中宅装饰,福州装修

在现代家居设计中&#xff0c;开放式布局越来越受到欢迎。它不仅可以提升家居的空间感&#xff0c;还可以促进家人之间的交流和互动。这个客厅、餐厅、阳台一体化的设计&#xff0c;更是充分利用了空间&#xff0c;具有多重亮点。 01.玄关到客厅嵌入式一体式收纳柜 玄关是进入…

全国高校走进深算院:共话国产数据库产教融合生态建设

近日&#xff0c;由教育部高等学校计算机类专业教学指导委员会、全国高等学校计算机教育研究会主办&#xff0c;清华大学出版社、深圳市信息技术应用创新联盟承办的“2023全国高校走进信创企业研学活动”顺利举办。来自全国各地30余家高校的近80位院校领导、教师代表走进了深圳…

windows启动后直接进入指定程序并且不显示欢迎界面和windows桌面

windows启动后直接进入指定程序并且不显示欢迎界面和windows桌面 前言开机进入指定程序方法问题 浅尝GINA和Credential Providers关闭欢迎屏幕 前言 由于系统需求需要做到电脑开机后显示完windows加载页面就直接进入自己系统的界面&#xff0c;并且不显示登录欢迎页面&#xf…

【收藏】SNMP介绍及使用

热门IT课程-视频教程&#xff1a;文章浏览阅读49次。认证课程介绍&#xff1a;华为HCIA试听课程 &#xff1a; 华为HCIA试听课程&#xff1a;华为HCIA试听课程&#xff1a;华为HCIP试听课程&#xff1a;思科CCNA试听课程&#xff1a;思科CCNA试听课程&#xff1a;思科CCNA试听课…

0x00000709一键修复的解决办法,0x00000709错误的原因

在使用打印机时&#xff0c;你可能会遇到一些错误代码&#xff0c;其中之一是0x00000709。这个错误代码表示无法设置默认打印机。如果你遇到这样的问题不用担心&#xff01;这篇文章将为你提供0x00000709一键修复的解决办法&#xff0c;帮助你解决0x00000709错误&#xff0c;并…

京东API接口的接入(京东工业)

在技术交流群&#xff0c;大家有探讨稳定获取京东商品主图、价格、标题&#xff0c;及sku的完整解决方案。这个引起了我技术挑战的兴趣。 目前&#xff0c;自己做了压测&#xff0c;QPS高、出滑块概率极低&#xff0c;API整体稳定&#xff0c;可满足业务场景的性能需求。 公共…

Electron+Ts+Vue+Vite桌面应用系列:sqlite增删改查操作篇

文章目录 1️⃣ sqlite应用1.1 sqlite数据结构1.2 初始化数据库1.3 初始化实体类1.4 操作数据类1.5 页面调用 优质资源分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418 ElectronTsVueVite桌面应用系列 &#xff1a;这个系列包括了从桌…

对一个预算有限的创业者来说,应该选择哪些形式的办公场地

对于一个预算有限的创业者来说&#xff0c;选择合适的办公场地是一个重要的决策。不同的办公场地形式有各自的优缺点&#xff0c;需要根据创业者的具体情况和需求来权衡。 一般来说&#xff0c;有以下几种常见的办公场地形式&#xff1a; - 家庭办公&#xff1a;这是最节省成本…

无需部署服务器,如何结合内网穿透实现公网访问导航页工具Dashy

文章目录 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一些网站聚合起来放在一起&#xff0c;形成自己的导航…

迅为iTOP-3568核心板在精准气象行业应用方案

迅为iTOP-3568核心板在精准气象行业应用方案 各位小伙伴们&#xff0c;今天我要给大家介绍一个非常厉害的项目&#xff0c;那就是3568核心板在精准气象方面的方案&#xff01;这个方案真的是太牛了&#xff0c;让人不禁感叹科技的强大&#xff01; 首先&#xff0c;让我们来了解…

主播岗位面试

一、自我介绍 在面试的开始阶段&#xff0c;你需要准备一个简洁而有力的自我介绍。这个自我介绍应该包括你的姓名、教育背景、工作经验以及你为何对这个主播职位感兴趣。这个自我介绍应该控制在1-2分钟之内&#xff0c;避免冗长的表述。 二、主播经历和特点 在这个环节&…

PC模糊搜索

双向绑定input输入框&#xff0c;监听值改变事件 <el-inputinput"input"v-model"queryParams.keyword"style"margin-bottom: 10px"type"text"prefix-icon"el-icon-search"size"small"placeholder"输入员工…