当前位置: 首页 > news >正文

关于Java 反射的简单易懂的介绍

目录

#0.总览

#1. 类的反射

①介绍

②获取

③作用

获取构造函数:

创建实例:

字段操作:      

方法操作:

获取修饰符:

#2.总结 


#0.总览

反射,官方是这样介绍它的:

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program.

翻译过来就是:反射是 Java 编程语言中的一项功能。它允许正在执行的 Java 程序检查或“内省”自身,并作程序的内部属性。

再翻译成人话就是:反射可以让程序可以把本身的各种方法,参数当作变量来使用。 

为什么翻译成“反射”?因为这个过程就像是照镜子:程序通过照镜子知道自己有什么方法和参数。

详细的说,有:

  • 获取类的信息(类名、方法、字段、构造方法等)。
  • 创建类的实例。
  • 调用类的方法、修改字段的值。
  • 动态地加载类和进行方法调用。
  • 与代理息息相关

#1. 类的反射

①介绍

        首先得介绍一下Class类

Class类是反射的核心部分

Class类和真实的类对象不是一个东西!Class类只是包含了对应类关于其涉及反射的一系列操作的类。每个类都会有属于自己的Class对象:

列如 String.class             Integer.class等

尝试输出:

System.out.println(String.class);

会得到 class java.lang.String

这是类的全限定类名,可以看成是类的标识。

②获取

通过一些方法,我们能获得一个类的Class对象:

Class ex1 = Class.forName("java.lang.String");

Class ex2 = String.class;

String string = new String();
Class ex3 = string.getClass();

那获取到Class类有什么用呢? 

③作用

获取构造函数:

拿这个类来举例:

public class Temp {
    public int a;
    public int b;
    private int c = 10;
    public Temp() {
    }
    public Temp(int a) {
        this.a = a;
    }
    private Temp(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public void sing(){
        System.out.println("ahhhhhh!");
    }
    private void dance(){
        System.out.println("haaaaaa!");
    }
}
Class ex = Temp.class;

ex.getConstructor();    ex.getConstructor(int.class);         

这会获得其一个指定的公共构造方法,注意!括号中的参数要这样写上对应的Class类才能获取到!

ex.getDeclaredConstructor();则可以获取到所有构造方法

相对的,Constructor<?>[] constructors = ex.getConstructors();则会获取所有公用构造方法

getDeclaredConstructors同理

       


创建实例:

Constructor constructor = ex.getConstructor(int.class);
Temp obj = (Temp) constructor.newInstance( 30);

这样就根据指定的构造方法创建出了一个指定的实例

       


字段操作: 

Temp obj = (Temp) constructor.newInstance( 30);
Field field = ex.getField("a");
System.out.println(field);
int value = field.getInt(obj); 
System.out.println(value);

这里会输出 30

注意!除了getInt还有getchar等对应基本数据类型,其他的统一为get()

但其实get()也能处理基本数据类型

格式为 Field.get(已实例化的对象)

对于私有变量,无独有偶:getDeclaredField(“c”)即可

但是只能System.out.println(field);,即获取全限定字段名,无法获得具体值!

解决方法在下:

但是对于字段修改: 

如果是公共字段:

field.set(obj, 666); 

就可以完成修改

私有字段是无法修改的!

必须先取消限制:

field.setAccessible(true);

这样才可以让私有字段像公共字段一样可以被查看,修改。


         

方法操作:

对于方法,有了前面的铺垫则简单得多:

对于公共方法:

Class ex = Temp.class;
Constructor constructor = ex.getConstructor();
Temp obj = (Temp) constructor.newInstance();

Method greetMethod = ex.getMethod("sing");
greetMethod.invoke(obj); 

这样就成功执行了sing方法

如果想要获取所有方法

Method[] methods = ex.getMethods();即可

但是必须要有一个已经实例化的对象obj才能正常的通过invoke操作来执行方法!

实际上,执行的方法实际上是已经实例化的obj里面对应的方法!

对于一些函数,可能名字相同但是参数不同,可以仿照构造函数那样加以区分:

Method greetMethod = ex.getMethod("sing",int.class);

Method greetMethod = ex.getMethod("sing",String.class);类似这样来区分

对于私有方法: 

和字段一模一样

在方法名上加上Declared

getDeclaredMethod,getDeclaredMethods

然后得加上greetMethod.setAccessible(true);才能正常操作


获取修饰符:

可以通过类似于:

int x = greetMethod.getModifiers();

来获取任何方法/字段的修饰符,也许你会疑惑为什么是int类型,原因是JAVA中的确是用数字来存储修饰符的,比如说:

public = 1, private = 2protected = 3,default= 4


 获取接口:

获取接口相对来说非常简单:

Class<?>[] interfaces = ex.getInterfaces();

这样便可获取所有ex类所实现的接口


获取注释:

Annotation[] annotations = ex.getAnnotations();

这样就获取了ex类所有的注释内容!

如果想获取方法的注释也非常简单:

Annotation[] annotations = ex.getMethod("xxx").getAnnotations();

(提一句,对于每个注释都是一个单独的类型,假如你需要@CY注释,改成
CY annotation = ex.getMethod("xxx").getAnnotation();也行)

接下来想要提取注释变量什么的就随你了

这种方法可以用来实现公共字段补全


#2.总结 

        归功于反射机制,程序得以对本身进行修改而不依赖于人工修改,也提供了更多的灵活性,

更是为实现动态代理提供了可能。

(我也写了一篇介绍代理的文章,欢迎捧场!)

你也许会发现,这种获取参数,接口,方法是不是很熟悉?是不是我们用的IDE就有点用了这种方式的意思?不然为什么我们写了一个函数就能提示要放什么参数进去?

这的确很像,但实际上IDE是会实时构造一个抽象语法树(AST),它是代码结构的表示。这使得 IDE 能够理解类、方法、字段和参数的存在及其类型。

尽管如此,反射非常重要,java,spring框架里面反射无处不在,

但是,反射的性能开销很大,因为它要在运行中实时解析类,方法,字段,这些原本是在编译时完成的,而且反射无法被编译器进行优化!

所以谨慎使用!

相关文章:

  • 一文熟练掌握Spring Framework
  • 以初学者视角探索智能体学习之旅
  • 新书上线 |《零门槛AIGC应用实战——Serverless+AI 轻松玩转高频AIGC场景》免费下载
  • upload-labs靶场
  • Spring Boot中整合Flink CDC 数据库变更监听器来实现对MySQL数据库
  • 【Python爬虫(48)】分布式爬虫:解锁多领域数据宝藏的密码
  • java Web
  • 宠物智能可穿戴产品调研报告
  • Microsoft Office 2024 软件安装教程(免费)
  • 前端八股——Vue3系列
  • Codeforces 559C 详细题解
  • 深入解析C++函数指针与指针函数:从原理到实战
  • 无法打开包括文件: “crtdbg.h”: No such file or directory
  • 【Blender】二、建模篇--06,曲线建模/父子级和蒙皮修改器
  • 《CentOS 7 镜像源失效终极解决方案(2024年更新)》——生命周期终止后的镜像修复与替代方案
  • Linux编程----filelo(2)
  • 【大模型LLM】DeepSeek LLM Scaling Open-Source Language Models with Longtermism
  • pandas Dataframe介绍以及创建
  • 使用 Python 调用 Ollama API 并调用 deepseek-r1:8b 模型
  • 【量化科普】Liquidity,流动性
  • 上海发布预付卡消费“10点提示”:警惕“甩锅闭店”套路
  • 高盛上调A股未来12个月目标点位,沪深300指数潜在回报15%
  • 公示!17个新职业、42个新工种亮相
  • 绿城房地产集团:近半年累计花费20.6亿元购买旗下债券
  • 习近平抵达莫斯科伏努科沃专机机场发表书面讲话(全文)
  • 线下无理由退货怎样操作?线上线下监管有何不同?市场监管总局回应