反射
为什么要使用反射
1 | //定义一个类 |
Person类是别人提供好的字节码文件.看不到源码是不能直接强转的.
不爽:我都已经获取到真正的对象了,居然不能知道他的真实类型.
什么是反射:
通过字节码(Class)对象,动态的获取该字节码中的成员(构造器,方法,字段,父类,包…)
字节码对象(Class):
将多个Class类抽象出来,形成一个字节码的结构(everything is object)
当JVM加载完字节码后.会使用一个对象,来描述该字节码文件的结构.该对象包含操作字节码中成员的方法.
字节码对象,是JVM加载字节码文件的时候,给我们创建的一个对象,一份字节码,只会创建一个字节码对象.
获取字节码对象的三种方法:
1.通过Class类的forName来获取.
public static Class<?> forName(String className):根据全限定名来获取字节码对象.
全限定名:包名.类名.指定到唯一的一个类上.
2.所有的对象,都有一个公共的方法.getClass.
public final Class<?> getClass(): 通过对象返回字节码对象.
3.任何类型都有一个class属性.
int.class / Person.class/
1 | package me.cscar.reflect.getClassObject; |
构造器的操作
获取构造器
获取单个构造器
parameterTypes:参数类型
想要定位到一个构造器,必须要指明构造器的参数列表.
1.获取单个构造器:
public Constructor<T> getConstructor(Class<?>... parameterTypes):获取public的指定的构造器
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) :获取不管权限的构造器
2.获取所有构造器:
Constructor<?>[] getConstructors() :获取所有public 的构造器
Constructor<?>[] getDeclaredConstructors() :获取所有构造器,不管权限.
1 | package me.cscar.reflect.getConstructor; |
通过构造器创建对象
public T newInstance(Object... initargs):通过构造器,创建对象.
initargs:实际参数.
如果想要调用私有的成员.必须要先设置可以访问.
public void setAccessible(boolean flag): 设置为true.
1 | package me.cscar.reflect.createObject; |
操作方法
获取方法
name:方法名
parameterTypes:参数列表的类型
想要定位到一个方法,必须要指定方法签名(方法名+参数列表)
1.获取多个方法
Method[] getMethods() :获取到所有的public方法,包括继承的.
Method[] getDeclaredMethods() :获取所有的方法,不包括继承的.
2.获取单个方法
Method getMethod(String name, Class<?>... parameterTypes) :获取指定的public方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes) :获取指定的方法,不管权限.
1 | package me.cscar.reflect.getMethod; |
反射的其他API
1 | package me.cscar.reflect.staticmethod; |