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 ...
随机推荐
- Redis Stack:基于Redis的搜索、文档、图形和时间序列功能
基于Redis的搜索.文档.图和时间序列功能整合到一个扩展Redis Stack中,以使开发人员能够轻松构建实时应用程序. Redis Stack 于 3 月 23 日发布,由三个组件组成: Redi ...
- Harbor 容器镜像仓库
Harbor仓库概述 Docker官⽅提供了Registry镜像仓库,但是Registry的功能相对简陋.Harbor是VMware公司提供的⼀款镜像仓库,提供了权限控制.分布式发布.强⼤的安全扫描与 ...
- 2023ccpc大学生程序设计竞赛-wmh
这算是我第一次参加这种团队赛,感谢程老师给我这个机会.刚开赛还算比较顺利,一眼看出来A是个签到,拿下之后开始跟榜F题.一开始想法比较简单,就是排序,记录相邻两个数的差,然后再排序.wa了后以为是范围出 ...
- Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream
伪 分布模式下启动spark报错 从spark1.4以后,所有spark的编译都是没有将hadoop的classpath编译进去的,所以必须在spark-env.sh中指定hadoop中的所有jar包 ...
- 是时候丢掉BeanUtils了
前言 为了更好的进行开发和维护,我们都会对程序进行分层设计,例如常见的三层,四层,每层各司其职,相互配合.也随着分层,出现了VO,BO,PO,DTO,每层都会处理自己的数据对象,然后向上传递,这就避免 ...
- linux设置信号量系统参数
前言 信号量是IPC(进程间通信)机制的一种,用于协调多个进程或线程对共享数据的读写操作,本质上是一个计数器.类似于锁,主要用于保护共享资源,控制同时访问资源的进程数. 信号量只允许调用者对它进行等待 ...
- 解决git出现fatal: detected dubious ownership in repository at XXXXX的错误
在window环境下,使用git命令时报错fatal: detected dubious ownership in repository at XXXXXX,图片如下 解决方法如下 添加一行代码 gi ...
- 轻松玩转70亿参数大模型!借助Walrus在AWS上部署Llama2
Llama 2 是 Meta 的下一代开源大语言模型.它是一系列经过预训练和微调的模型,参数范围从 70 亿到 700 亿个.Meta Llama 2 可免费用于研究和商业用途并且提供了一系列具有不同 ...
- 【io_uring】内核源码分析(更新中)
文章目录 `io_uring` 系统调用 `io_uring_setup` `io_uring_setup` `io_uring_create` `io_sq_offload_start` 系统调用 ...
- 《SQL与数据库基础》20. 主从复制
目录 主从复制 原理 搭建 主库配置 从库配置 测试 本文以 MySQL 为例 主从复制 主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执 ...