反射基础知识第一篇

时间:2022-01-15 15:18:43

类被加载后,系统都会生成一个该类对应的Class对象。利用这个Class对象,我们可以访问这个类的构造器、方法、属性等,这就叫做反射。

一.在程序中获取该类对应的Class对象,有3种方式:

1.利用Class类的forName(String className)静态方法

Class clazz = null;
try {
clazz = Class.forName("com.activiti.util.A");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
注意本方法会抛出ClassNotFoundException异常,要么抛出,要么try catch捕获,如果try catch的话,clazz变量的声明要在try catch语句外面,否则就变成局部变量,要使用必须在try语句中了。

2.利用类名.class的方式

Class clazz = A.class;
3.利用该类从Object类继承的getClass()实例方法,调用此方法时需要一个该类的对象,但是在没办法获得该类对象的时候(比如说是个接口或是该类没有提供public的构造器及返回类型是该类类型的public的方法),此方法就失效了

Class clazz = new A().getClass();

二.利用该类对应的Class对象,得到该类的构造器、方法、属性(或者说是成员变量)

public final class Constructor<T> extends AccessibleObject implements GenericDeclaration,Member{ }
public final class Method extends AccessibleObject implements GenericDeclaration,Member { }
public final class Field extends AccessibleObject implements Member { }
从以上可以看出,Constructor、Method、Field都是final class且都继承了AccessibleObject并实现了Member接口。

1.获取该类的构造器Constructor

在编辑器中通过clazz打点可以看到与构造器有关的方法有4个,两个方法名,每个方法名有两种重载:

public Constructor<T> getConstructor(Class<?>... parameterTypes)

public Constructor<?>[] getConstructors() throws SecurityException

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes

public Constructor<?>[] getDeclaredConstructors() throws SecurityException

这里值得注意的是,declaredXXX方法表示获取的构造器不限访问权限,包括public的和非public的,而非declared方法则表示只能获取访问权限是public的构造器。

方法里的参数Class对象是要获取的构造器的形参类型的Class对象,因为构造器可能有多个重载,所以只能以构造器的参数列表来区分要获取哪个构造器。例如

Constructor Constructor = null;
try {
Constructor = clazz.getConstructor(String.class, int.class);
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
}
上面getConstructor(String.class, int.class)方法的返回值就是clazz对应类的public的、有两个参数,且第一个参数类型是String,第二个参数类型是int的构造器。如果在该对应类中没有声明这样的构造器,则会报NoSuchMethodException异常。

getConstructors()、getDeclaredConstructors()则分别表示所有的public的构造器、所有的构造器,返回类型均为Constructor数组。

2.获取该类的方法Method,不区分静态非静态

public Method getMethod(String name, Class<?>... parameterTypes)
public Method[] getMethods() throws SecurityException
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public Method[] getDeclaredMethods() throws SecurityException
方法意思同上面获取构造器的方法相似,例如

Method method = null;
try {
method = clazz.getDeclaredMethod("hh", String.class, int.class);
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
}
上面clazz.getDeclaredMethod("hh", String.class, int.class)方法的返回值是clazz对应类的方法名称是hh,有两个参数,且第一个参数类型是String,第二个参数类型是int的方法,可能是static的,也可能是static,总的一句话,跟方法是否是静态方法无关,只跟访问权限和参数列表类型有关。

3.获取该方法的成员变量

public Field getField(String name)
public Field[] getFields() throws SecurityException
public Field getDeclaredField(String name)
public Field[] getDeclaredFields() throws SecurityException

方法意思也是同上面获取构造器的方法相似,例如

Field field = null;
try {
field = clazz.getField("age");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
上面clazz.getField("age")返回值是clazz对应类中的public的、名称是age的成员变量,同样跟静态非静态无关。如果对应类中有此成员变量则返回,否则会报NoSuchFieldException异常。