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 ...
随机推荐
- 从逻辑门到 CPU
目的,造一个很简单的,概念上的 CPU,虽然简单,但是是五脏俱全的 CPU 从最基础的逻辑门开始造,零基础可以看 制造基本武器:与门.非门.或门 现在计算机都是二进制,那二进制是一开始就能想到的吗?显 ...
- C++与Java共同点
前言 首先我们来了解一下C++语言,大多人都C++语言是C语言基础上的改编,所以它拥有一个和C语言一样的类似结构,但是它与Java又有不可分割的关系 接下来我们来看几道题: 例如:常数O运行次数与N大 ...
- KVM (Centos7)使用macvtap网卡的后续 -- 宿主机创建macvtap网卡,并配置ip
因为使用虚拟机上的 macvtap 网卡与宿主机器上的网卡无法直接通信,所以需要在宿主机上也创建 macvtap 网卡,将 ip 迁移过去. 因为未能找到配置文件的设置方法,所以使用脚本来配置,并将脚 ...
- typroa文件迁移时的图片问题
如下图所示设置即可 会自动在同级目录中创建img文件夹,并存储图片
- 高效构建 vivo 企业级网络流量分析系统
作者:vivo 互联网服务器团队- Ming Yujia 随着网络规模的快速发展,网络状况的良好与否已经直接关系到了企业的日常收益,故障中的每一秒都会导致大量的用户流失与经济亏损.因此,如何快速发现网 ...
- Codeforces 1850H:The Third Letter 带权并查集
1850H.The Third Letter Description: \(n\) 个人,\(m\) 个条件,每次给出两个人 \(a_i\) 和 \(b_i\) 一维的位置关系,以距离 \(d_i\) ...
- SpringBoot对接OpenAI
SpringBoot对接OpenAI 随着人工智能技术的飞速发展,越来越多的开发者希望将智能功能集成到自己的应用中,以提升用户体验和应用的功能.OpenAI作为一家领先的人工智能公司,提供了许多先进的 ...
- async、await其实是generator和promise的语法糖
async 关键字用于声明异步函数,await 用于在async函数中将异步代码变为同步,阻塞代码的执行 对于promise和generator不熟悉的朋友可以移步看看这些文章 Promise的理解与 ...
- quarkus依赖注入之十三:其他重要知识点大串讲(终篇)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<quarkus依赖注入> ...
- 【pandas小技巧】--日期相关处理
日期处理相关内容之前pandas基础系列中有一篇专门介绍过,本篇补充两个常用的技巧. 1. 多列合并为日期 当收集来的数据中,年月日等信息分散在多个列时,往往需要先合并成日期类型,然后才能做分析处理. ...