专栏首页gfujava反射机制简单介绍

java反射机制简单介绍

不慌,先来一波介绍

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。

读完解释,接着来!

反射机制的好处

应用场景

在运行时判定任意一个对象所属的类

逆向代码 ,例如反编译

在运行时构造任意一个类的对象

与注解相结合的框架

在运行时判定任意一个类所具有的成员变量和方法

单纯的反射机制应用框架

在运行时调用任意一个对象的方法

动态生成类框架(GSon)

生成动态代理

优点

运行期类型的判断,动态类加载,动态代理使用反射。

缺点

性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。

用处

在基础框架的搭建上非常用,但是在业务上用处很少,如果有想成为架构师的,可以仔细研究一波

  1. class对象获取的三种方式
//第一种方式 通过对象getClass方法
Person person = new Person();
Class<?> class1 = person.getClass();
//第二种方式 通过类的class属性
class1 = Person.class;
try {
    //第三种方式 通过Class类的静态方法——forName()来实现
    class1 = Class.forName("com.reflectdemo.Person");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}
  1. 获取class对象的摘要信息
boolean isPrimitive = class1.isPrimitive();//判断是否是基础类型
boolean isArray = class1.isArray();//判断是否是集合类
boolean isAnnotation = class1.isAnnotation();//判断是否是注解类
boolean isInterface = class1.isInterface();//判断是否是接口类
boolean isEnum = class1.isEnum();//判断是否是枚举类
boolean isAnonymousClass = class1.isAnonymousClass();//判断是否是匿名内部类
boolean isAnnotationPresent = class1.isAnnotationPresent(Deprecated.class);//判断是否被某个注解类修饰

String className = class1.getName();//获取class名字 包含包名路径
Package aPackage = class1.getPackage();//获取class的包信息
String simpleName = class1.getSimpleName();//获取class类名
int modifiers = class1.getModifiers();//获取class访问权限

Class<?>[] declaredClasses = class1.getDeclaredClasses();//内部类
Class<?> declaringClass = class1.getDeclaringClass();//外部类
  1. 获取class对象的属性、方法、构造函数等
Field[] allFields = class1.getDeclaredFields();//获取class对象的所有属性
Field[] publicFields = class1.getFields();//获取class对象的public属性
try {
    Field ageField = class1.getDeclaredField("age");//获取class指定属性
    Field desField = class1.getField("des");//获取class指定的public属性
} catch (NoSuchFieldException e) {
    e.printStackTrace();
}

Method[] methods = class1.getDeclaredMethods();//获取class对象的所有声明方法
Method[] allMethods = class1.getMethods();//获取class对象的所有方法 包括父类的方法

Class parentClass = class1.getSuperclass();//获取class对象的父类
Class<?>[] interfaceClasses = class1.getInterfaces();//获取class对象的所有接口

Constructor<?>[] allConstructors = class1.getDeclaredConstructors();//获取class对象的所有声明构造函数
Constructor<?>[] publicConstructors = class1.getConstructors();//获取class对象public构造函数
try {
    Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{String.class});//获取指定声明构造函数
    Constructor publicConstructor = class1.getConstructor(new Class[]{});//获取指定声明的public构造函数
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

Annotation[] annotations = class1.getAnnotations();//获取class对象的所有注解
Annotation annotation = class1.getAnnotation(Deprecated.class);//获取class对象指定注解

Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 Type
Type[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的type集合
  1. class对象动态生成
//第一种方式 Class对象调用newInstance()方法生成
Object obj = class1.newInstance();
//第二种方式 对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{String.class});//获取指定声明构造函数
obj = constructor.newInstance(new Object[]{"object"});
  1. 动态调用函数
try {
    // 生成新的对象:用newInstance()方法
    Object obj = class1.newInstance();
    //判断该对象是否是Person的子类
    boolean isInstanceOf = obj instanceof Person;
    //首先需要获得与该方法对应的Method对象
    Method method = class1.getDeclaredMethod("setAge", new Class[]{int.class});
    //调用指定的函数并传递参数
    method.invoke(obj, 28);
    method = class1.getDeclaredMethod("getAge");
    Object result = method.invoke(obj, new Class[]{});
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
  1. 通过反射机制获取泛型类型
#例子
//People类
public class People<T> {}
//Person类继承People类
public class Person<T> extends People<String> implements PersonInterface<Integer> {}
//PersonInterface接口
public interface PersonInterface<T> {}


#获取泛型类型
Person<String> person = new Person<>();
//第一种方式 通过对象getClass方法
Class<?> class1 = person.getClass();
Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 Type
Type[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的Type集合

getComponentType(genericSuperclass);
getComponentType(interfaceTypes[0]);

#getComponentType具体实现
private Class<?> getComponentType(Type type) {
Class<?> componentType = null;
if (type instanceof ParameterizedType) {
    //getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
    Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
    if (actualTypeArguments != null && actualTypeArguments.length > 0) {
    componentType = (Class<?>) actualTypeArguments[0];
    }
} else if (type instanceof GenericArrayType) {
    // 表示一种元素类型是参数化类型或者类型变量的数组类型
    componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType();
} else {
    componentType = (Class<?>) type;
}
return componentType;
}
  1. 通过反射机制获取注解信息
try {
    //首先需要获得与该方法对应的Method对象
    Method method = class1.getDeclaredMethod("jumpToGoodsDetail", new Class[]{String.class, String.class});
    Annotation[] annotations1 = method.getAnnotations();//获取所有的方法注解信息
    Annotation annotation1 = method.getAnnotation(RouterUri.class);//获取指定的注解信息
    TypeVariable[] typeVariables1 = method.getTypeParameters();
    Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();//拿到所有参数注解信息
    Class<?>[] parameterTypes = method.getParameterTypes();//获取所有参数class类型
    Type[] genericParameterTypes = method.getGenericParameterTypes();//获取所有参数的type类型
    Class<?> returnType = method.getReturnType();//获取方法的返回类型
    int modifiers = method.getModifiers();//获取方法的访问权限
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何处理java中对{},[],() 的解析,不仅可以用正则,也可以用堆栈的方式,算法的想法做

    gfu
  • git revert和git reset 回家加图

    1.git reset git reset有3个参数,可以自行百度,主要介绍--hard git reset hard 版本号 这个命令不推荐使用后,这样会...

    gfu
  • mybatis-plus的使用

    多表的分页只需要在Mapper里的方法中传入Page这个对象就可以自动分页了,mybatis-plus是基于mybatis,也要引入对应的包。本项目是基于gra...

    gfu
  • Springboot 系列(三)Spring Boot 自动配置

    关于配置文件可以配置的内容,在 Spring Boot 官方网站已经提供了完整了配置示例和解释。

    未读代码
  • 【Java编程实战】Metasploit_Java后门运行原理分析以及实现源码级免杀与JRE精简化

    某日午睡迷迷糊糊梦到Metasploit里有个Java平台的远控载荷,梦醒后,打开虚拟机,在框架中搜索到了这个载荷

    重生信息安全
  • 一文了解ConfigurationConditon 接口

    在了解ConfigurationCondition 接口之前,先通过一个示例来了解一下@Conditional 和 Condition。(你也可以通过 http...

    cxuan
  • Spring、SpringMVC、SpringBoot之间的关系

    随着微服务架构的兴起,SpringBoot映入眼帘,今天我们来说下三者的含义以及关系。

    别明天就今天吧
  • 第十一章:高级(企业级)特性

    Quartz集群目前与JDBC-Jobstore(JobStoreTX或JobStoreCMT)和(<–译者注:其实我觉得这里应该是"或")Terracotta...

    Throwable
  • adb 常用命令大全(3)- 查看手机设备信息

    其中 scale 代表最大电量,level 代表当前电量。上面的输出表示还剩下 50% 的电量。

    小菠萝测试笔记
  • 简洁实用的Redis分布式锁用法

    在微服务中很多情况下需要使用到分布式锁功能,而目前比较常见的方案是通过Redis来实现分布式锁,网上关于分布式锁的实现方式有很多,早期主要是基于Redisson...

    JAVA葵花宝典

扫码关注云+社区

领取腾讯云代金券