反射
1、反射
Java 反射机制是在 运行时 动态的获取信息和调用对象的方法,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性
程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的
1.1 反射的作用
-
可以实现简单的反编译,获取类中的属性和方法等基本信息
-
获取类的属性、方法等,甚至可以调用 private 方法
-
在使用 IDE 时,当输入一个对象或类并想调用它的属性或方法时,输入点号,编译器就会自动列出它的属性或方法
-
最重要的用途就是开发各种通用框架。很多框架都是配置化的,比如通过 XML 文件配置 Bean,为了保证框架的通用性,可能需要根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射,运行时动态的加载需要加载的对象
1.2 反射的优点
- 提高程序的灵活性和扩展性,降低耦合性
- 允许程序创建和控制任何类的对象,无需提前硬编码目标类
1.3 反射的缺点
-
影响性能:使用反射时,代码量更多,并且反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多,应该避免在经常被执行的代码或对性能要求很高的程序中使用反射
-
安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行
-
破坏封装性:由于反射允许代码执行一些在正常情况下不被允许的操作,如访问私有的属性和方法,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化
1.4 Class 对象
在类加载器将 .class
文件读取到内存中的时候,JVM 会创建这个 .class
文件的对象,并且只创建一个存放到 JVM 的方法区内存中,即 在运行期间,一个类,只有一个 Class 对象产生。在 java.lang
包下有个 Class 类,这个类就是 .class
文件的对象类型,任何类在被使用时,都会创建这个类的 Class 对象。反射相关的类一般都在 java.lang.relfect
包里
Class 和 java.lang.reflect
一起对反射提供了支持,java.lang.reflect
类库主要包含了以下三个类
- Field :可以使用 get 和 set 方法读取和修改 Field 对象关联的字段
- Method :可以使用 invoke 方法调用与 Method 对象关联的方法
- Constructor :可以用 Constructor 创建新的对象
1.4.1 获取 Class 对象的三种方式
- 调用某个对象的 getClass 方法,不常用,已经有对象了,需要反射的意义不大
Class one = test.getClass();
- 使用 Class 类的 forName 静态方法,常用,字符串可以传入也可写在配置文件中等多种方法
Class two = Class.forName("com.test.Test");
- 直接获取某一个对象的 class,不常用,需要导入类的包,依赖太强,不导包就抛编译错误
Class three = Test.class;
1.5 使用反射创建对象
1.6 获取方法
1.6.1 获得方法数组
Method[] getDeclaredMethods() |
Method[] getMethods() |
---|---|
获取类或接口的 所有方法 | 获取类或接口的 所有公共方法 |
不包括继承的方法 | 包括继承的方法(公共方法) |
- 输出了 Person 类的所有方法
private void com.test.Person.run()
public void com.test.Person.show()
public void com.test.Person.say(java.lang.String)
- 只输出了 Person 类的公共方法,并且输出了隐含继承的 Object 类的公共方法
public void com.test.Person.show()
public void com.test.Person.say(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
1.6.2 获取方法
Method getDeclaredMethod() |
Method getMethod() |
---|---|
获取类或接口中的方法 | 获取类或接口中的 公共方法 |
不包括继承的方法 | 包括继承的方法(公共方法) |
public void com.test.Person.show()
public void com.test.Person.say(java.lang.String)
private void com.test.Person.run()
- 可以输出隐含继承的 Object 类的 hashCode 方法
public void com.test.Person.show()
public void com.test.Person.say(java.lang.String)
public native int java.lang.Object.hashCode()
1.6.3 获取构造方法数组
public com.test.Person()
public com.test.Person(java.lang.String)
private com.test.Person(int)
public com.test.Person()
public com.test.Person(java.lang.String)
1.6.4 获取构造方法
public com.test.Person()
public com.test.Person(java.lang.String)
private com.test.Person(int)
public com.test.Person()
public com.test.Person(java.lang.String)
1.6.5 使用反射调用类中的方法
- 可以使用
void setAccessible(true)
方法,之后调用私有方法或成员变量
1.7 获取成员变量
1.7.1 获取成员变量数组
Field[] getDeclaredMethod() |
Field[] getMethod() |
---|---|
获取类或接口的所有的成员变量 | 获取类或接口的所有的 公共成员变量 |
不包括继承的成员变量 | 包括继承的成员变量(公共成员变量) |
public int com.test.Person.x
public java.lang.String com.test.Person.y
int com.test.Person.z
public int com.test.Person.x
public java.lang.String com.test.Person.y
public float com.test.Human.f
1.7.2 获取成员变量
public int com.test.Person.x
public java.lang.String com.test.Person.y
int com.test.Person.z
public int com.test.Person.x
public java.lang.String com.test.Person.y
public float com.test.Human.f
1.7.3 使用反射获取类中指定的属性并赋值
1.8 获取父类或父接口
更多:深入解析 Java反射(1)、深入解析 Java反射(2)
__EOF__

本文链接:https://www.cnblogs.com/holyholic/p/13669841.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)