Java---反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。
在执行程序(java.exe)时候,将字节码文件读入JVM中--->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象-->这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。
所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。
如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

补充:
动态语言vs静态语言
1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以
被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运
行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、
C++。

所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动
态性,我们可以利用反射机制、字节码操作  获得类似动态语言的特性。
Java的动态性让编程的时候更加灵活! 

 Class类的理解

 获取运行时类的完整结构

1、获取构造器和创建对象

package com.zhaoss.test03;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test01 {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//获取字节码信息:Class cls = Student.class;//通过字节码信息可以获取构造器://getConstructors只能获取当前运行时类的被public修饰的构造器Constructor[] c1 = cls.getConstructors();1for(Constructor c:c1){System.out.println(c);}System.out.println("-------------------");//getDeclaredConstructors:获取运行时类的全部修饰符的构造器Constructor[] c2 = cls.getDeclaredConstructors();for(Constructor c:c2){System.out.println(c);}System.out.println("-------------------");//获取指定的构造器://得到空构造器Constructor con1 = cls.getConstructor();System.out.println(con1);//得到两个参数的有参构造器:Constructor con2 = cls.getConstructor(double.class, double.class);System.out.println(con2);//得到一个参数的有参构造器:并且是private修饰的Constructor con3 = cls.getDeclaredConstructor(int.class);System.out.println(con3);//有了构造器以后我就可以创建对象:Object o1 = con1.newInstance();System.out.println(o1);Object o2 = con2.newInstance(180.5, 170.6);System.out.println(o2);}
}

2、获取属性和对属性进行赋值

package com.zhaoss.test03;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test02 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {//获取运行时类的字节码信息:Class cls = Student.class;//获取属性://getFields:获取运行时类和父类中被public修饰的属性Field[] fields = cls.getFields();for(Field f:fields){System.out.println(f);}System.out.println("---------------------");//getDeclaredFields:获取运行时类中的所有属性Field[] declaredFields = cls.getDeclaredFields();for(Field f:declaredFields){System.out.println(f);}System.out.println("---------------------");//获取指定的属性:Field score = cls.getField("score");System.out.println(score);Field sno = cls.getDeclaredField("sno");System.out.println(sno);System.out.println("---------------------");//属性的具体结构://获取修饰符/*int modifiers = sno.getModifiers();System.out.println(modifiers);System.out.println(Modifier.toString(modifiers));*/System.out.println(Modifier.toString(sno.getModifiers()));//获取属性的数据类型:Class clazz = sno.getType();System.out.println(clazz.getName());//获取属性的名字:String name = sno.getName();System.out.println(name);System.out.println("-------------------------------");//给属性赋值:(给属性设置值,必须要有对象)Field sco = cls.getField("score");Object obj = cls.newInstance();sco.set(obj,98);//给obj这个对象的score属性设置具体的值,这个值为98System.out.println(obj);}
}

3、获取方法和调用方法

package com.zhaoss.test03;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test03 {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {//获取字节码信息:Class cls = Student.class;//获取方法://getMethods:获取运行时类的方法还有所有父类中的方法(被public修饰)Method[] methods = cls.getMethods();for(Method m:methods){System.out.println(m);}System.out.println("-----------------------");//getDeclaredMethods:获取运行时类中的所有方法:Method[] declaredMethods = cls.getDeclaredMethods();for(Method m:declaredMethods){System.out.println(m);}System.out.println("-----------------------");//获取指定的方法:Method showInfo1 = cls.getMethod("showInfo");System.out.println(showInfo1);Method showInfo2 = cls.getMethod("showInfo", int.class, int.class);System.out.println(showInfo2);Method work = cls.getDeclaredMethod("work",int.class);System.out.println(work);System.out.println("-----------------------");//获取方法的具体结构:/*@注解修饰符 返回值类型  方法名(参数列表) throws XXXXX{}*///名字:System.out.println(work.getName());//修饰符:int modifiers = work.getModifiers();System.out.println(Modifier.toString(modifiers));//返回值:System.out.println(work.getReturnType());//参数列表:Class[] parameterTypes = work.getParameterTypes();for(Class c:parameterTypes){System.out.println(c);}//获取注解:Method myMethod = cls.getMethod("myMethod");Annotation[] annotations = myMethod.getAnnotations();for(Annotation a:annotations){System.out.println(a);}//获取异常:Class[] exceptionTypes = myMethod.getExceptionTypes();for(Class c:exceptionTypes){System.out.println(c);}//调用方法:Object o = cls.newInstance();myMethod.invoke(o);//调用o对象的mymethod方法System.out.println(showInfo2.invoke(o,12,45));;}
}

4、获取类的接口,所在包,注解

package com.zhaoss.test03;
import java.lang.annotation.Annotation;
public class Test04 {public static void main(String[] args) {//获取字节码信息:Class cls = Student.class;//获取运行时类的接口:Class[] interfaces = cls.getInterfaces();for(Class c:interfaces){System.out.println(c);}//得到父类的接口://先得到父类的字节码信息:Class superclass = cls.getSuperclass();//得到接口:Class[] interfaces1 = superclass.getInterfaces();for(Class c:interfaces1){System.out.println(c);}//获取运行时类所在的包:Package aPackage = cls.getPackage();System.out.println(aPackage);System.out.println(aPackage.getName());//获取运行类的注解:Annotation[] annotations = cls.getAnnotations();for(Annotation a:annotations){System.out.println(a);}}
}

总结

  • 反射机制是一项强大的功能,允许开发者动态地操作类和对象,增强了代码的灵活性。
  • Java 本身是静态语言,但通过反射机制,能够在某些方面具备动态语言的特性。
  • 反射提供了对类结构的深入访问,开发者可以通过它获取和操作类的各种信息,为框架设计和工具开发提供了强大的支持。

反射虽然带来灵活性,但也可能引入性能开销和安全风险,因此需要谨慎使用。

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

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

相关文章

Mac配置maven环境及在IDEA中配置Maven

Mac配置maven环境及在IDEA中配置Maven 1. 介绍 Maven是一款广泛用于Java等JVM语言项目的工具,它以项目对象模型(POM)为基础进行项目管理,通过POM文件来定义项目信息和依赖关系。同时,它也是构建自动化工具&#xff0…

知乎日报——第二周

知乎日报——第二周 文章目录 知乎日报——第二周本周总结ModelViewController无限右滑预加载 总结 本周总结 本周主要完成了知乎日报的详情页面,实现了无限右滑和动态申请详情页的内容,实现了预先加载。以及通过位置获取相应的格外信息,使用…

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2

七、创建前端项目 你下载了nodejs吗?从cn官网下载:http://nodejs.cn/download/,或者从一个国外org网站下载,选择自己想要的版本https://nodejs.org/download/release/,双击下载好的安装文件,选择安装路径安…

Windows 软件之 FFmpeg

文章目录 前言1 FFmpeg 视频处理1.1 编解码1.2 其它视频编辑命令1.3 视频抽帧 2 FFmpeg 音频处理3 FFmpeg 图片处理3.1 编解码3.2 拼接图片3.3 图片合成视频 附录1:mediainfo.ps1 前言 FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的…

Docker1:认识docker、在Linux中安装docker

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

MATLAB的addpath和rmpath函数增加或删除路径

在进行MBD建模开发时,模型生成代码时常需要加载一些其他的文件,例如代码生成模版文件cgt文件、模型所涉及的头文件,这个时候可以在模型的回调函数中使用addpath和rmpath函数加载和删除路径,例如设置模型的加载之前的回调函数在模型…

【FPGA开发】Vivado自定义封装IP核,绑定总线

支持单个文件的封装、整个工程的封装,这里用单个文件举例。 在文件工程目录下,自建一个文件夹,里面放上需要封装的verilog文件。 选择第三个,指定路径封装,找到文件所在目录 取个名,选择封装IP的路径 会…

前端速通(CSS)

1.CSS介绍 1.什么是CSS? CSS(Cascading Style Sheets,层叠样式表)是一种用于控制网页的外观和布局的样式表语言。它与HTML(超文本标记语言)紧密配合,负责页面元素的样式定义,如字体、颜色、尺…

Android 13 编译Android Studio版本的Launcher3

Android 13 Aosp源码 源码版本 Android Studio版本 Launcher3QuickStepLib (主要代码) Launcher3ResLib(主要资源) Launcher3IconLoaderLib(图片加载,冲突资源单独新建) 需要值得注意的是: SystemUISharedLib.jar 有kotlin和java下的,在 Lau…

idea添加版权信息

1、添加Copyright Profiles 打开Settings -> Editor -> Copyright -> Copyright Profiles -> 新增 Copyright (c) 【你的版权信息】 【开始年份】-${today.year}. All rights reserved.如: Copyright (c) by cwp 2024-${today.year}. All rights rese…

【计算机网络】多路转接之poll

poll也是一种linux中的多路转接方案(poll也是只负责IO过程中的"等") 解决:1.select的fd有上限的问题;2.每次调用都要重新设置关心的fd 一、poll的使用 int poll(struct pollfd *fds, nfds_t nfds, int timeout); ① struct pollfd *fds&…

【C语言】深入剖析 C 语言中数组与指针的紧密联系及高效应用

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯例一:指针偏移遍历数组1.1 代码回顾1.2 代码分析1.3 理论扩展:数组与指针的关系1.4 数组与指针的应用场景 💯例二:自定义…

基于SpringBoot的数据结构系统设计与实现(源码+定制+开发)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…

算法训练-双指针

双指针 leetcode392. 判断子序列 法一:动态规划 法二:双指针 leetcode876. 链表的中间结点 法一:链表数组 法二:快慢指针 leetcode160. 相交链表 法一:双指针 leetcode167. 两数之和 II - 输入有序数组 法一&…

零基础学指针(上)

系列文章目录 🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼 🎉🎉我的C语言初阶合集:C语言初阶合集,希望能…

shell编程之sed

sed 是一种流编辑器,它是文本处理中非常有用的工具,能够完美的配合正则表达式使用,处理时,把当前处理的行存储在临时缓冲区中,称为模式空间,接着用sed 命令处理缓冲区中的内容,处理完成 后&…

一文学习开源框架OkHttp

OkHttp 是一个开源项目。它由 Square 开发并维护,是一个现代化、功能强大的网络请求库,主要用于与 RESTful API 交互或执行网络通信操作。它是 Android 和 Java 开发中非常流行的 HTTP 客户端,具有高效、可靠、可扩展的特点。 核心特点 高效…

多目标优化算法:多目标极光优化算法(MOPLO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码

一、极光优化算法 极光优化算法(Polar Lights Optimization, PLO)是2024年提出的一种新型的元启发式优化算法,它从极光这一自然现象中汲取灵感。极光是由太阳风中的带电粒子在地球磁场的作用下,与地球大气层中的气体分子碰撞而产…

【贪心算法第二弹——2208.将数组和减半的最小操作数】

1.题目解析 题目来源 2208.将数组和减半的最小操作数——力扣 测试用例 2.算法原理(贪心策略) 3.实战代码 class Solution { public:int halveArray(vector<int>& nums) {priority_queue<double> hash;double sum 0.0;for(auto e : nums){hash.push(e);sum …

2024最新python使用yt-dlp

2024最新python使用yt-dlp下载YT视频 1.获取yt的cookie1&#xff09;google浏览器下载Get cookies.txt LOCALLY插件2&#xff09;导出cookie 2.yt-dlp下载[yt-dlp的GitHub地址](https://github.com/yt-dlp/yt-dlp?tabreadme-ov-file)1&#xff09;使用Pycharm(2024.3)进行代码…