什么是Java反射:作用、使用方法、原理三方面解析

Java反射是Java进阶编程内容之一,掌握反射应用与原理,有助于我们理解一些框架(Spring)和插件(junit)的运行原理。

一、Java反射的作用

简单来说,Java反射主要有两个作用:

  1. 使得程序符合开关原则:实体如类、模块和函数应该对扩展开放,对修改关闭。用户注册公司的平台需要短信验证码,为了防止接入的短信平台故障导致公司的注册业务无法正常营运,常使用1+1做故障转移。这种情况即可使用反射,读取数据库或缓存里的数据,在不修改业务代码的前提下,切换平台。

  2. 不知道实现类的情况下,开发应用或者设计框架:其实这和第一条有点相似,但程序员变成了用户。IDEA的智能提示、Spring的xml配置、junit的测试注解,都大量使用了反射。在正常情况下,我们会使用new关键字实例化一个对象,这是在明确class类的情况下。作为框架的开发者,他们无法得知用户(程序员)使用了什么类,用什么修饰符,类名叫什么,这种情况下,反射的作用就体现出来了。

二、使用方法

1. 反射的使用步骤:

  • Apple类

    public class Apple {private int price;public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}
    }
    
  • 1.获取类的 Class 对象实例

    Class clz = Class.forName("com.zhenai.api.Apple");
    
  • 2.根据 Class 对象实例获取 Constructor 对象

    Constructor appleConstructor = clz.getConstructor();
    
  • 3.使用 Constructor 对象的 newInstance 方法获取反射类对象

    Object appleObj = appleConstructor.newInstance();
    
  • 4.而如果要调用某一个方法,则需要先获取对象,再使用对象调用invoke方法:

    Method setPriceMethod = clz.getMethod("setPrice", int.class);
    setPriceMethod.invoke(appleObj, 14);
    
  • 完整代码

    public class Apple {private int price;public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public static void main(String[] args) throws Exception{//new 关键字实例化Apple apple = new Apple();apple.setPrice(5); // 调用方法System.out.println("Apple Price:" + apple.getPrice());//使用反射调用Class clz = Class.forName("com.chenshuyi.api.Apple");Method setPriceMethod = clz.getMethod("setPrice", int.class);Constructor appleConstructor = clz.getConstructor();Object appleObj = appleConstructor.newInstance();setPriceMethod.invoke(appleObj, 14);  //调用方法Method getPriceMethod = clz.getMethod("getPrice");System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));}
    }
    
  • 输出

    Apple Price:5
    Apple Price:14
    

到这里,我们已经能够掌握反射的基本使用。除了这些方法,Java还提供了其他的反射API

2.Java反射API
获取反射中的Class对象在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。在 Java API 中,获取 Class 类对象有三种方法:

  • 第一种,使用 Class.forName 静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。

    Class clz = Class.forName("java.lang.String");
    
  • 第二种,使用 .class 方法。这种方法只适合在编译前就知道操作的 Class。

    Class clz = String.class;
    
  • 第三种,使用类对象的 getClass() 方法。

    String str = new String("Hello");
    Class clz = str.getClass();
    

通过反射创建类对象主要有两种方式:

  • 通过 Class 对象的 newInstance() 方法。

    Class clz = Apple.class;
    Apple apple = (Apple)clz.newInstance();
    
  • 通过 Constructor 对象的 newInstance() 方法

    Class clz = Apple.class;
    Constructor constructor = clz.getConstructor();
    Apple apple = (Apple)constructor.newInstance();
    
  • 通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。

    Class clz = Apple.class;
    Constructor constructor = clz.getConstructor(String.class, int.class);
    Apple apple = (Apple)constructor.newInstance("红富士", 15);
    

通过反射获取类属性、方法、构造器

  • 我们通过 Class 对象的 getFields() 方法可以获取 Class 类的属性,但无法获取私有属性。而如果使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性:

    Class clz = Apple.class;
    Field[] fields = clz.getDeclaredFields();
    for (Field field : fields) {System.out.println(field.getName());
    }
    
  • 输出结果是:name

price与获取类属性一样,当我们去获取类方法、类构造器时,如果要获取私有方法或私有构造器,则必须使用有 declared 关键字的方法。

(三)、反射原理

反射原理本质上还是运用的Java面向对象的思想,简单来说,JDK把我们的类当作一个对象,把对象分解为一个个的属性,并提供一些方法或者辅助对象操作属性。具体的解析放一篇
某乎链接供大家深入了解。

最后贴一点反射的优缺点:
优点:

  • 能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
  • 与 Java 动态编译相结合,可以实现无比强大的功能。
  • 对于 Java 这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:

  • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;(据我所知,目前已经有一些插件可以缓解资源问题)
  • 反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。

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

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

相关文章

【漏洞复现】WordPress_Wholesale_Market admin-ajax.php 任意文件读取漏洞

0x01 产品简介 WordPress Wholesale Market是一个WordPress主题,专门设计用于创建批发市场和在线商城网站。该主题提供了许多功能和设计元素,使您能够轻松地构建一个功能强大的批发市场平台,以满足批发商和零售商的需求。 0x02 漏洞概述 WordPress Wholesale Market存在任…

VL02N交货单清除字段:VLSTK(分配状态)

VL02N交货单清除字段:VLSTK(分配状态) 通过查找增强对应的BADI:LE_SHP_DELIVERY_PROC 修改方法:IF_EX_LE_SHP_DELIVERY_PROC~CHANGE_DELIVERY_HEADER,代码如下:

AngularJS中文手册后半部分学习

AngularJS 简介 AngularJS的中文参考手册 AngularJS 表格 结合ng-repeat命令 <div ng-app"myApp" ng-controller"customersCtrl"><table><tr ng-repeat"x in names"><td>{{ x.Name }}</td><td>{{ x.Coun…

#QT获取ONENET云平台数据(草稿)

1.基本目标 &#xff08;1&#xff09;查询ONENT云平台的数据 &#xff08;2&#xff09;查询网络时间 &#xff08;3&#xff09;网络音乐拉取&#xff08;作为背景音乐&#xff09;&#xff0c;音量可调 2.制作UI界面 &#xff08;1&#xff09;串口图标的制作方法 &…

天星金融(原小米金融)履行社会责任,提高社保政策知晓度

二十大报告指出“为民造福是立党为公、执政为民的本质要求“&#xff0c;人民幸福安康是推动高质量发展的最终目的。社会保障作为维护社会公平、增进人民福祉的基本制度&#xff0c;既是“安全网”也是“稳定器”&#xff0c;发挥着改善民生的重要作用。为进一步提升人民群众对…

如何解决DDoS攻击?群联科技做出回答。

DDoS攻击&#xff08;分布式拒绝服务攻击&#xff09;是一种恶意利用多台傀儡机协同发起大规模网络流量&#xff0c;旨在压垮目标系统或网络资源&#xff0c;使其无法正常服务的网络攻击手段。由于现代计算机和网络性能的提升&#xff0c;单点发起的DoS攻击已难以奏效&#xff…

独立样本t检验——python完整代码(直接运行就行)

#!/usr/bin/env python # -*- coding: utf-8 -*- # Author : 三十二画生JH # Contact : fjhstudent163.com # Software: PyCharm # Time : 2024/4/21 21:49 # Site : 网址 # File : t_test.py # Version : # ---功能描述 """ 对实验数据做独立样本&am…

速盾:不备案能用国内cdn吗?

在中国&#xff0c;所有的CDN&#xff08;内容分发网络&#xff09;服务都需要进行备案&#xff0c;这是根据相关法律法规的要求。备案是指网站所有者必须向中国互联网络信息中心&#xff08;CNNIC&#xff09;提交相关信息&#xff0c;以便在中国境内使用CDN服务。 备案的目的…

博客网站/部署服务器---继上篇前端页面接入后端

目录 准备工作 创建用户类博客类与连接数据库 创建博客类 创建用户类 创建连接数据库工具类 实现对数据库数据博客的操作 实现对数据库用户的操作 创建数据库语句 登录页面 前端 后端 博客列表 前端 注销登录 写入数据 判断用户是否登录 替换页面用户昵称 后…

Scala详解(4)

Scala 面向对象 案例 定义类表示矩形(Rectangle)&#xff0c;提供对外获取周长(girth)和面积(area)的函数&#xff0c;并且为这个矩形类提供一个子类表示正方形(Square) package com.fesco.exer ​ object ObjectDemo1 { ​def main(args: Array[String]): Unit { ​val r …

永恒之蓝上线CS

该文介绍了在内网环境下&#xff0c;利用永恒之蓝漏洞&#xff08;EternalBlue&#xff09;将攻击者控制台&#xff08;CS&#xff09;上线的方法。前提条件是目标机器可上网、无防火墙和杀毒软件&#xff0c;并且存在永恒之蓝漏洞。使用Erebus插件的eterblue功能&#xff0c;通…

xpath的使用以及原理-元素定位

# 查找文本框输入文本 driver.find_element(By.CLASS_NAME,"nav-search-input").send_keys("i_cecream查找到了") #查找到之后点击 driver.find_element(By.CLASS_NAME,"nav-search-btn").click()time.sleep(30)selenium4的解析。 client调用se…

Kimi智能助手:您的个性化AI伙伴

目录 智能对话伙伴:kimi 功能部分 对话能力:多语言支持与深度交流

2024团体程序设计天梯赛L1-103 整数的持续性

题目链接L1-103 整数的持续性 #include<iostream> #include<stdio.h> #include<algorithm> using namespace std; struct node{int x;int d; }p[2000]; bool cmp(node a, node b) {if (a.d b.d) return a.x < b.x;return a.d>b.d; } int cnt, cntt; v…

信号----硬件中断

硬件中断 键盘组合键是向进程发送信号&#xff0c;那么键盘数据是如何输入到内核中&#xff0c;然后变成信号的&#xff1f;这个信号又是由谁发送给进程的&#xff1f; 当键盘被按下&#xff0c;操作系统先知道用户用键盘输入了内容 那么操作系统是如何知道键盘上有内容了&…

【Camera Sensor Driver笔记】二、点亮指南之Sensor Module XML

Camera Sensor module XML详解&#xff1a; cameraId 与 slot id 一一对应 &#xff08;即&#xff1a;dtsi中相对应的sensor的 cell-index &#xff09; moduleName 模组厂名称 sensorName sensor 名称 actuatorName 马达名称 oisName …

学习亚马逊云科技AWS云计算技术的三款官方免费3A游戏大作

玩3A大作免费电脑游戏&#xff0c;就能成为AWS云架构师、云开发大&#x1f42e;&#xff1f;这么好的事尊的假的&#xff1f;小李哥今天就来给大家介绍&#xff0c;如何通过玩AWS官方的定制版虚拟人生、炉石传说和密室逃脱游戏学习AWS。这三个游戏完全免费&#xff0c;没有任何…

如何利用pg_dump和pg_restore迁移从一个PostgreSQL服务器到另一个服务器,同时保持一致性与高效性?

文章目录 解决方案1. 使用pg_dump导出数据2. 将导出的数据复制到目标服务器3. 使用pg_restore导入数据保持一致性与高效性的策略一致性高效性 示例代码导出数据复制数据到目标服务器在目标服务器上解压并导入数据 PostgreSQL数据库的迁移是一个常见的任务&#xff0c;特别是在升…

如何在PostgreSQL中使用CTE(公共表表达式)来简化复杂的查询逻辑?

文章目录 解决方案步骤示例代码 结论 在处理复杂的SQL查询时&#xff0c;我们经常会遇到需要多次引用子查询或中间结果的情况。这可能会使得查询变得冗长且难以理解。为了解决这个问题&#xff0c;PostgreSQL&#xff08;以及其他一些SQL数据库系统&#xff09;引入了公共表表达…

springdoc-openapi使用

springdoc-openapi使用 一、引入pom二、新增配置类OpenApiConfig四、Controller层示例五、配置文件新增内容六、验证 一、引入pom <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1…