Java反射机制

1. 简介

Java反射机制是让我们能够在运行期访问和调用类、接口的属性、方法的机制,它通过将上述的类、接口、属性、方法映射成一个个对象来实现,所以,简言之,Java反射机制是使我们能够像操作对象一样来操作上述目标的一种机制。
Java语言的反射机制是强大而实用的,例如,大名鼎鼎的Spring中的IOC底层实现原理就是Java反射机制,由Spring容器创建实例,通过解析xml文件中的id和class等相关属性,创建实例对象,再将它们放入bean容器中。

2. 反射

2.1 类

你可以通过Java的反射机制在运行期获得类的如下信息:

  • Class对象
  • 类名
  • 修饰符
  • 包信息
  • 父类
  • 实现的接口
  • 构造器
  • 方法
  • 属性
  • 注解

2.1.1 Class对象

Class对象可以通过Class clazz=Class.forName(className),className是一个字符串,表示目标的全类名。获取类全名的方式:Aclass.getName(),如果不需要全名,那么使用getSimpleNmae()可以获得不包括包名的简单类名。如果调用Class.forName()找不到该类,则抛出ClassNotFoundException

2.1.2修饰符

即public、private、static之类的关键字
这里修饰符被包装为int类型,这样,每个修饰符都是一个标识位,我们可以通过设置、清除来改变修饰符的类型。int modifiers=clazz.getModifiers();java.lang.reflect.Modifier类设置了大量的方法用来检查修饰符的类型:

Modifier.isAbstract(int modifiers);
Modifier.isFinal(int modifiers);
Modifier.isInterface(int modifiers);
Modifier.isNative(int modifiers);
Modifier.isPrivate(int modifiers);
Modifier.isProtected(int modifiers);
Modifier.isPublic(int modifiers);
Modifier.isStatic(int modifiers);
Modifier.isStrict(int modifiers);
Modifier.isSynchronized(int modifiers);
Modifier.isTransient(int modifiers);
Modifier.isVolatile(int modifiers);

2.1.3 其它信息

  • 包信息:Package package = clazz.getPackage();
  • 父类:Class superclass = clazz.getSuperclass();
  • 接口信息:Class[] interfaces = clazz.getInterfaces();
  • 构造器:Constructor[] constructors = clazz.getConstructors();
  • 方法:Method[] method = clazz.getMethods();
  • 属性(变量):Field[] method = clazz.getFields();
  • 注解:Annotation[] annotations = clazz.getAnnotations();

这里我们需要注意一点,interfaces这个数组中包含的是clazz类显式实现的接口,父类实现的接口是不会被获取的。

2.2 构造器

2.2.1 获取构造器对象

由于一个类可能拥有一个以上的构造器,因此我们获取构造器的方法返回一个公有构造器的数组:Constructor[] constructors = clazz.getConstructors();。除此之外,我们可以获取指定参数的构造器Constructor[] constructors = clazz.getConstructors(new Class[]{String.class});,这里构造方法的参数就是String类型,如果没有该参数的方法会抛出NoSuchMethodException

2.2.2 构造方法参数

我们可以通过Class[] parameterTypes = constructor.getParameterTypes();来获取指定构造器的方法参数列表。

2.2.3 使用构造器实例化一个类

调用构造器的newInstance()方法可以实例化一个类对象,该方法返回类型为Object,例如:MyObject myObject = (MyObject)constructor.newInstance(constructor-arg1);这里newInstance()方法可以接收一个参数列表,但形参与实参必须一一对应。

2.3 变量(Field)

2.3.1 获取Field对象

上面已经说了一种获取Field数组的方法,现在我们还能够获取指定的Field,如果你知道属性名的话:Field field = clazz.getField("someField");,如果目标类没有对应属性,那么抛出NoSuchFieldException

2.3.2 变量名和变量类型

这两个比较简单:

  • 变量名:String fieldName = field.getName();
  • 变量类型:Object fieldType = field.getType();

2.3.3 Field的set/get方法

通过Field的get与set方法,我们可以轻易地获取改变对象的属性值,

Class  clazz= MyObject.class
Field field = clazz.getField("someField");

MyObject objectInstance = new MyObject();
//获取对象的属性,这里如果field是静态变量的话,
//我们就无需传入该类的实例,传入null即可
Object value = field.get(objectInstance);
//设置对象的属性
field.set(objetInstance, value);

2.3 方法(Method)

2.3.1 获取Method对象

前面已经提到了一种获取类的公共的Method列表的方式,现在我们介绍一种可以获得指定Method的方式:
Method method = aClass.getMethod("methodName", new Class[]{String.class});
,这里方法的名称就叫做methodName,方法的参数时String类型

2.3.2 方法参数及返回类型

  • 方法参数类型列表:Class[] parameterTypes = method.getParameterTypes();
  • 方法返回类型:Class returnType = method.getReturnType();

2.3.3 通过Method对象调用方法

//获取一个方法名为doSomesthing,参数类型为String的方法
Method method = MyObject.class.getMethod("doSomething", String.class);
Object returnValue = method.invoke(null, "parameter-value1");

这里invoke(Object target, Object … parameters)方法的第一个参数应当是该方法所属类的实例对象,但是此处我们假设该方法时一个静态方法,所以传入null即可,后面是一个参数列表,可以传入多个参数。
//TODO
先写一点基础的,剩下的有空再写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值