浅学java反射一:认识反射

112 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

前言:

我们知道java是面向对象的语言,一切都是对象,我们在一般都会使用new关键字来创建对象,其实java还提供了一种创建对象的方式,那就是java的反射机制。

一、反射是什么?

官方文档中对反射的解释:反射(Reflection) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性和方法。

简单来说就是我们不用在编译期就确定对象的类型,将确定对象类型这一步放到程序运行期去了。现在不理解这句话没事,看完反射这一系列的文章后你会理解这句话的。

二、反射常用Api

Class

Clase对象里面是存的类的一些信息

  • 怎样获取Class对象
User user = new User();  // 使用new关键字
Class.forName("user");  // Class.forName()
Class<? extends User> userByGetClass = user.getClass();  // 对象的getClass();
Class<User> userClass = User.class; // 类.class
  • Class对象常用Api
    • class.newInstance():调用缺省构造函数,返回该对象的一个实例
    • class.getDeclaredFields():返回field对象的一个数组,所有访问修饰符的字段类型
    • class.getFields():获取public修饰的属性字段
    • class.getClassLoader():返回该类的类加载器
    • class.getSuperclass():返回该类的父类
    • class.getMethods():返回该对象的所有方法

Api较多,就不一一列出来,大家可以自行去了解下

Field

  • 怎样获取Field对象(通过class对象获取)

    • Class.getFields():获取public修饰的属性字段。
    • getDeclaredFields():获取类中所有属性(public protect default private)不包括继承父类中的字段。
    • getField(String name):获取类特定的方法,name 参数指定了属性的名称
    • getDeclaredField(String name):获取类特定的方法,name 参数指定了属性的名称
  • Field 对象常用Api

    • field.setAccessible(boolean flag):启用或禁用安全检查,true禁用,false启用
    • field.getType():返回这个变量的类型
    • filed.getName():返回这个属性的名称
    • field.get(Object obj):返回指定对象obj上此字段的值
    • field.set(Object obj, Object value):设置obj对象的当前字段值为value;

Method

  • 怎样获取Method对象(通过class对象获取)

    • class.getMethods():获取类中被public修饰的方法
    • class.getMethod(String name, Class... paramTypes):根据名称和参数类型获取对应方法,只能获取被public修饰的方法,否则会报NoSuchMethodException错误
    • class.getDeclaredMethods():获取所有方法(排除继承父类的方法).
    • class.getDeclaredMethod(String name, Class... paramTypes):根据名字和参数类型获取对应方法.
  • Method 对象常用Api

    • method.getName():获取方法名
    • method.getReturnTypes():获取返回值的类型
    • method.getParameterTypes():获取参数类型的数组
    • method.invoke(Object obj,Object…args):为object对象执行此方法。如果为静态方法obj传null即可,非静态方法需要传对象实例
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Method stringMethod = String.class.getMethod("valueOf", Object.class);
    Integer num = 5;
    Object invoke = stringMethod.invoke(null, num);
    String typeName = invoke.getClass().getTypeName();
    System.out.println(invoke);  // 5
    System.out.println(typeName);  // java.lang.String
}

Constructor

  • 怎样获取Constructor对象(通过class对象获取)

    • class.getConstructor(Class..c);获得某个公共的构造方法
    • class.getConstructors();获得所有的公共构造方法。
    • class.getDeclaredConstructor(Class..c);获得某个构造方法。(任意访问修饰符的构造方法都能获取)
    • class.getDeclaredConstructors();获得所有的构造方法。(任意访问修饰符的构造方法都能获取)
  • Constructor 对象常用Api

    • constructor.getName();获得方法名
    • constructor.newInstance(Object...args);使用当前的构造方法来创建一个对象;

Annotation

  • 怎样获取Annotation对象(Class、Field、Method、Constructor都可以获取到)
    • Annotation[] getAnnotations():获取该对象上的所有注解集合
    • Annotation getAnnotation(Class annotaionClass):获取此对象上指定的注解
    • Annotation[] getDeclaredAnnotations():获取该对象上的所有注解,会忽略继承的注解
    • Annotation getDeclaredAnnotation(Class annotationClass):根据注解类型获得此对象上的注解,会忽略继承的注解

关于getAnnotations()和getDeclaredAnnotations()的差别可以看stackoverflow社区的回答stackoverflow.com/questions/1…

  • Annotation 对象常用Api
    • annotation.annotationType():获取注解的类型 返回值是一个class对象

总结

这篇文章主要是罗列出来一些常用的反射api,像上面的class、method、field中的api都是会经常用到的,本节还没有实际用到其中的api,下一章我会总结一下我在项目中用到反射的一些场景,还会带大家看一下一些开源框架中对于反射的用法,下一章是干货,大家一定不要错过哦。