反射简介

反射是Java的高级特性之一,但是在实际的开发中,使用Java反射的案例却非常的少,但是反射确实在底层框架中被频繁的使用。

比如:JDBC中的加载数据库驱动程序,Spring框架中加载bean对象,以及态代理,这些都使用到反射,因为我们要想理解一些框架的底层原理,反射是我们必须要掌握的。

理解反射我们先从他的概念入手,那么什么是反射呢?

反射就是在运行状态能够动态的获取该类的属性和方法,并且能够任意的使用该类的属性和方法,这种动态获取类信息以及动态的调用对象的方法的功能就是反射。

实现上面操作的前提是能够获取到该类的字节码对象,也就是.class文件,在反射中获取class文件的方式有三种:

  1. 类名.class 如:Person.class
  2. 对象.class 如:person.class
  3. Class.forName(全类名)获取 如:Class.forName("ldc.org. demo.person")

这里有点区别的就是使用1,2(.class)方式获取Class对象,并不会初始化Class对象,而使用3(forName("全类名"))的方式会自动初始化Class对象。


反射

反射对应到Java中的类库就是在java.lang.reflect下,在该包下包含着FieldMethodConstructor类。

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)的更多相关文章

  1. Spring + MyBaits java.lang.reflect.InvocationTargetException 启动日志报错

    调试发现 实例化 class org.apache.ibatis.logging.slf4j.Slf4jImpl时发生异常,所以 slf4j jar 问题解决: http://www.cnblogs. ...

  2. [spring] java.lang.reflect.MalformedParameterizedTypeException

    spring中加入dubbo后报java.lang.reflect.MalformedParameterizedTypeException 因为dubbo 2.5.3 它引用的是spring 2.5. ...

  3. JAVA反射系列之Field,java.lang.reflect.Field使用获取方法

    JAVA反射系列之Field,java.lang.reflect.Field使用获取方法.   转载https://my.oschina.net/u/1407116/blog/209383 摘要 ja ...

  4. JAVA中反射机制五(java.lang.reflect包)

    一.简介 java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口.反射API允许对程序访问有关加载类的字段,方法和构造函数的信息进行编程访问.它允许在安全限制内使用反射的字段, ...

  5. java反射(java.lang.reflect) ---普通单例模式唯一性问题

    1. 普通的饱汉式.饿汉式 package org.bighead.test2; public class TestPrivate { private String str = "strPr ...

  6. Java反射API研究(2)——java.lang.reflect详细内容与关系

    对于最新的java1.8而言,reflect中接口的结构是这样的: java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedType ...

  7. JAVA中反射机制六(java.lang.reflect包)

    一.简介 java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口.反射API允许对程序访问有关加载类的字段,方法和构造函数的信息进行编程访问.它允许在安全限制内使用反射的字段, ...

  8. springmvc错误集锦-dubbo包含低版本的spring包,依赖的时候应该排除Caused by: java.lang.reflect.MalformedParameterizedTypeException

    dubbo 常见错误 1. Caused by: java.lang.reflect.MalformedParameterizedTypeException 启动时报错,原因是dubbo 依赖 spr ...

  9. java反射(java.lang.reflect)---java.lang.reflect.Modifier中状态码

    1. 详情请看jvm(虚拟机)规范 java.lang.reflect.Modifier public static final int ABSTRACT 1024 public static fin ...

  10. java.lang.reflect.Method.getAnnotation()方法示例【通过反射获取到方法对象再获取方法对象上的注解信息】

    转: java.lang.reflect.Method.getAnnotation()方法示例 java.lang.reflect.Method.getAnnotation(Class <T&g ...

随机推荐

  1. Java_Day17_作业

    1:需求:递归删除带内容的目录 假设删除当前项目下的目录:demo,demo中可以有文件夹自己给出 2:需求:请大家把E:\JavaSE目录下所有的java结尾的文件的绝对路径给输出在控制台. 3:下 ...

  2. 根据图片搜索excel

    问题描述:在excel使用中,当我们用大量的excel记录图文信息的时候,如果excel过多,比如成百上千个,里面都是包含大量的图片.这个时候如果想要根据图片快速找到这张图片可能被哪些excel包含, ...

  3. 【游戏开发笔记】编程篇_C#面向对象{上}

    @ 目录 1.变量和表达式 1.1注释 1.2C#控制台程序基本结构 1.3变量(从存储长度来看) 1.4变量的命名 1.5字面值 1.6运算符 2流程控制 2.1分支 2.2循环 3变量知识拓展 3 ...

  4. 达梦数据库: SQL查询报错《不是 GROUP BY 表达式解决方法》

    报错信息: ****: 第4 行附近出现错误: 不是 GROUP BY 表达式 修改办法: 达梦可以配置兼容参数,COMPATIBLE_MODE=4,静态参数,需要重启数据库后生效! sp_set_p ...

  5. 论文解读(DWL)《Dynamic Weighted Learning for Unsupervised Domain Adaptation》

    [ Wechat:Y466551 | 付费咨询,非诚勿扰 ] 论文信息 论文标题:Dynamic Weighted Learning for Unsupervised Domain Adaptatio ...

  6. SpringBoot3进阶用法

    标签:切面.调度.邮件.监控: 一.简介 在上篇<SpringBoot3基础>中已经完成入门案例的开发和测试,在这篇内容中再来看看进阶功能的用法: 主要涉及如下几个功能点: 调度任务:在应 ...

  7. AVR汇编(三):寻址方式

    AVR汇编(三):寻址方式 AVR具有多种寻址方式,在介绍具体的汇编指令之前,有必要对它们做一定了解. 前面介绍过,AVR将内存空间分为多个部分:寄存器堆.I/O空间.数据空间.程序空间.这些空间支持 ...

  8. 论文解读(MetaAdapt)《MetaAdapt: Domain Adaptive Few-Shot Misinformation Detection via Meta Learning》

    Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:MetaAdapt: Domain Adaptive Few-Shot Misinformation De ...

  9. PIP升级+安装Django命令[WARNING: Retrying (Retry(total=4, connect=None...]

    升级: >pip install -U Django 安装: >pip install Django 如果发现超时错误内容:(WARNING: Retrying (Retry(total= ...

  10. 如何基于 Kubernetes 实现优质开发者平台体验?

    内部开发者平台(或 IDP)是使开发团队能够更快.更轻松.更一致地交付应用程序的基础设施.Kubernetes 本身是一个功能强大的平台,但它引入了太多复杂性和功能,因此不能简单地将其作为 IDP 交 ...