spring---反射(java.lang.reflect)
反射简介
反射是Java的高级特性之一,但是在实际的开发中,使用Java反射的案例却非常的少,但是反射确实在底层框架中被频繁的使用。
比如:JDBC中的加载数据库驱动程序,Spring框架中加载bean对象,以及态代理,这些都使用到反射,因为我们要想理解一些框架的底层原理,反射是我们必须要掌握的。
理解反射我们先从他的概念入手,那么什么是反射呢?
反射就是在运行状态能够动态的获取该类的属性和方法,并且能够任意的使用该类的属性和方法,这种动态获取类信息以及动态的调用对象的方法的功能就是反射。
实现上面操作的前提是能够获取到该类的字节码对象,也就是.class文件,在反射中获取class文件的方式有三种:
- 类名.class 如:Person.class
- 对象.class 如:person.class
- Class.forName(全类名)获取 如:Class.forName("ldc.org. demo.person")
这里有点区别的就是使用1,2(.class)方式获取Class对象,并不会初始化Class对象,而使用3(forName("全类名"))的方式会自动初始化Class对象。
反射
反射对应到Java中的类库就是在java.lang.reflect下,在该包下包含着Field、Method和Constructor类。
Field: 表示一个类的属性信息
Method: 表示类的方法信息
Constructor: 表示的是类的构造方法的信息
在反射中常用的方法,我这里做了一个列举,当然更加详细的可以查官方的API文档进行学习。
| 方法名 | 作用 |
|---|---|
| getConstructors() | 获取公共构造器 |
| getDeclaredConstructors() | 获取所有构造器 |
| newInstance() | 获取该类对象 |
| getName() | 获取类名包含包路径 |
| getSimpleName() | 获取类名不包含包路径 |
| getFields() | 获取类公共类型的所有属性 |
| getDeclaredFields() | 获取类的所有属性 |
| getField(String name) | 获取类公共类型的指定属性 |
| getDeclaredField(String name) | 获取类全部类型的指定属性 |
| getMethods() | 获取类公共类型的方法 |
| getDeclaredMethods() | 获取类的所有方法 |
| getMethod(String name, Class[] parameterTypes) | 获得类的特定公共类型方法 |
| getDeclaredClasses() | 获取内部类 |
| getDeclaringClass() | 获取外部类 |
| getPackage() | 获取所在包 |
User 类:
点击查看代码
package com.example.zhangchonghu.demo.controller.reflect;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/17 11:20
* @Version 1.0
*/
public class User {
private String name;
public Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
private void privateMethod() {
System.err.println("私有方法执行了");
}
public void publicMethod(String param){
System.err.println("公有方法执行了,参数为:"+param);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
在User的实体类中,有两个属性age和name,并且除了有两个测试方法privateMethod和publicMethod用于测试私有方法和公共方法的获取。接着执行如下代码:
点击查看代码
package com.example.zhangchonghu.demo;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Description:
* @author: 张重虎
* @Date: 2022/2/17 11:54
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
public class TestReflect {
@Test
public void test() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, ClassNotFoundException {
//1、类名.class
/**
* Class clazz = User.class;
*/
//2、对象.class
/**
* User user = new User();
* Class clazz = user.getClass();
*/
//3、Class.forName(全类名)获取
Class clazz = Class.forName("com.example.zhangchonghu.demo.controller.reflect.User");
Constructor constructor = clazz.getConstructor(String.class, Integer.class);
//获取该类对象并设置属性的值
Object obj = constructor.newInstance("张三", 18);
//获得类全类名,既包含包路径
String fullClassName = clazz.getName();
//获得类名
String className = clazz.getSimpleName();
//获取类中公共类型(public)属性
Field[] fields = clazz.getFields();
String fieldName = "";
for (Field field : fields) {
//获取属性名
fieldName = field.getName();
System.out.println("public 属性名为:" + fieldName);
}
//获取类中所有的属性,包括 private 属性
Field[] fieldsAll = clazz.getDeclaredFields();
fieldName = "";
for (Field field : fieldsAll) {
fieldName = field.getName();
System.out.println("private 属性名为:" + fieldName);
}
//获取指定公共属性值
Field age = clazz.getField("age");
Object value = age.get(obj);
System.err.println("公共指定属性:" + value);
//获得指定的私有属性值
Field name = clazz.getDeclaredField("name");
//设置为true才能获取私有属性
name.setAccessible(true);
Object value2 = name.get(obj);
System.err.println("私有指定属性值:" + value2);
//获取所有公共类型方法 这里包括 Object 类的一些方法
Method[] methods = clazz.getMethods();
String methodsName = "";
for (Method method : methods) {
methodsName = method.getName();
System.out.println("公开的方法:" + methodsName);
}
//获取该类中的所有方法(包括private)
Method[] methodsAll = clazz.getDeclaredMethods();
methodsName = "";
for (Method method : methodsAll) {
methodsName = method.getName();
System.out.println("私有的方法:" + methodsName);
}
//获取并使用指定方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod");//获取无参私有方法
privateMethod.setAccessible(true);
privateMethod.invoke(obj);//调用方法
Method publicMethod = clazz.getMethod("publicMethod", String.class);//获取有参数方法
publicMethod.invoke(obj, "张三");//调用有参方法
}
}
运行结果(多次运行结果顺序不相同,盲猜是和多线程有关。埋个雷,没有深入挖掘):

反射在jdk 1.5的时候允许对Class对象能够支持泛型,也称为泛化Class,具体的使用如下:
Class<User> user= User.class;
//泛化class可以直接得到具体的对象,而不再是Object
Useruser= user.newInstance();
泛化实现了在获取实例的时候直接就可以获取到具体的对象,因为在编译器的时候就会做类型检查。当然也可以使用通配符的方式,例如:Class<?>
反射优点和缺点
优点:反射可以动态的获取对象,调用对象的方法和属性,并不是写死的,比较灵活,比如你要实例化一个bean对象,你可能会使用new User()写死在代码中。
但是使用反射就可以使用class.forName(user).newInstance(),而变量名user可以写在xml配置文件中,这样就不用修改源代码,灵活、可配置。
缺点:反射的性能问题一直是被吐槽的地方,反射是一种解释操作,用于属性字段和方法的接入时要远远慢于直接使用代码,因此普通程序也很少使用反射。
spring---反射(java.lang.reflect)的更多相关文章
- Spring + MyBaits java.lang.reflect.InvocationTargetException 启动日志报错
调试发现 实例化 class org.apache.ibatis.logging.slf4j.Slf4jImpl时发生异常,所以 slf4j jar 问题解决: http://www.cnblogs. ...
- [spring] java.lang.reflect.MalformedParameterizedTypeException
spring中加入dubbo后报java.lang.reflect.MalformedParameterizedTypeException 因为dubbo 2.5.3 它引用的是spring 2.5. ...
- JAVA反射系列之Field,java.lang.reflect.Field使用获取方法
JAVA反射系列之Field,java.lang.reflect.Field使用获取方法. 转载https://my.oschina.net/u/1407116/blog/209383 摘要 ja ...
- JAVA中反射机制五(java.lang.reflect包)
一.简介 java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口.反射API允许对程序访问有关加载类的字段,方法和构造函数的信息进行编程访问.它允许在安全限制内使用反射的字段, ...
- java反射(java.lang.reflect) ---普通单例模式唯一性问题
1. 普通的饱汉式.饿汉式 package org.bighead.test2; public class TestPrivate { private String str = "strPr ...
- Java反射API研究(2)——java.lang.reflect详细内容与关系
对于最新的java1.8而言,reflect中接口的结构是这样的: java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedType ...
- JAVA中反射机制六(java.lang.reflect包)
一.简介 java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口.反射API允许对程序访问有关加载类的字段,方法和构造函数的信息进行编程访问.它允许在安全限制内使用反射的字段, ...
- springmvc错误集锦-dubbo包含低版本的spring包,依赖的时候应该排除Caused by: java.lang.reflect.MalformedParameterizedTypeException
dubbo 常见错误 1. Caused by: java.lang.reflect.MalformedParameterizedTypeException 启动时报错,原因是dubbo 依赖 spr ...
- java反射(java.lang.reflect)---java.lang.reflect.Modifier中状态码
1. 详情请看jvm(虚拟机)规范 java.lang.reflect.Modifier public static final int ABSTRACT 1024 public static fin ...
- java.lang.reflect.Method.getAnnotation()方法示例【通过反射获取到方法对象再获取方法对象上的注解信息】
转: java.lang.reflect.Method.getAnnotation()方法示例 java.lang.reflect.Method.getAnnotation(Class <T&g ...
随机推荐
- 2023年郑州轻工业大学校赛邀请赛zzh
第一次参加线下赛体验很好,面包和酸奶很好吃.ABL三题难度超出我们的能力范围,没能写出来,C题在读完题后,我们三个简单交流了一下,确定思路后我写的代码,一次AC,很顺利.D题简单的01背包,但我在写代 ...
- Windows10 下 Neo4j1.5.8 安装教程
前言 Neo4j 是一个高性能的.NOSQL 图形数据库,它将结构化数据存储在网络上而不是表中.基于磁盘的.具备完全的事务特性的 Java 持久化引擎,这里就不把他和常用关系型数据库做对比了.因为篇幅 ...
- UPS设备在物流机房中的应用浅析
1 UPS 简介 UPS 即不间断电源 (Uninterruptible Power Supply),是一种含有储能装置的不间断电源.主要用于给部分对电源稳定性要求较高的设备,提供不间断的电源. 当市 ...
- React错误: Can't resolve 'react-dom/client'
错误截图 解决方案 当你的react版本低于18时,但仍然报这个错误,可以采用如下方案 意外的发现当我采用上述方案时,我的React路由跳转时,页面不刷新的问题也解决了,很神奇,日后技艺精进再补充.
- error: failed to push some refs to 'https://gitee.com/xxxxxxxxx/xxxxxxxt'
原因是ReadMe文件不在本地中, 此时我们要执行git pull --rebase origin master命令README.md拉到本地, 任何然后执行git push origin maste ...
- Pytorch 最全入门介绍,Pytorch入门看这一篇就够了
本文通过详细且实践性的方式介绍了 PyTorch 的使用,包括环境安装.基础知识.张量操作.自动求导机制.神经网络创建.数据处理.模型训练.测试以及模型的保存和加载. 1. Pytorch简介 在这一 ...
- [db2]缓冲池管理
简介 缓冲池指的是从硬盘读取表和索引数据时,数据库管理器分配的用于高速缓存这些表和索引数据的内存区域.每个数据库都必须具有至少一个缓冲池,创建数据库时会自动创建一个名为IBMDEFAULTBP的缓冲池 ...
- Linux系统启动jmeter可视化界面
目的:方便在Linux系统调试jmeter脚本.操作:Linux启动jmeter可视化界面,不能使用root用户,需要创建新用户,切换到新用户启动jmeter. 1. 创建用户 创建一个新的系统用户. ...
- 论文解读(SentiX)《SentiX: A Sentiment-Aware Pre-Trained Model for Cross-Domain Sentiment Analysis》
Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:SentiX: A Sentiment-Aware Pre-Trained Model for Cross ...
- [ABC305C] Snuke the Cookie Picker题解
题目大意 有一个 \(H\times W\) 的网格,一种有一个矩形,矩形中间有一个点被挖空,求这个点的坐标.(. 表示空白,# 表示矩形内的点) 解析 观察我们可以发现,每一矩形内的个点上下左右至少 ...