Java中的反射机制

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

1.什么是反射?

反射是通过 Class 对象(字节码文件),来知道某个类的所有属性和方法。也就是说通过反射我们可以获取构造器,对象,属性,方法(原本不知道),之后在 JAVA 框架中,很多类我们是看不见的,不能直接用类名去获取对象,只能通过反射去获取。反射是框架设计的灵魂,可以将框架中的类的各个组成部分封装为其他对象并且操纵这些对象,来实现解耦提高程序的扩展性。
通过 Java 反射机制,可以在程序中访问已经装载到 JVM 中的 Java 对象的描述,实现访问、检测和修改描述 Java 对象本身信息的功能。Java 反射机制的功能十分强大,在java.lang.reflect包中提供了对该功能的支持。

2.通过反射可访问的主要描述信息

图片

在通过getFields()方法和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过getDeclaredFields()方法和getDeclaredMethods()方法只是获得在本类中定义的所有成员变量和方法。
现对访问构造方法、访问成员变量、访问成员方法做出解释。

3.访问构造方法

在通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法:

图片

如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。例如,访问一个入口参数类型依次为 String 型和 int 型的构造方法,通过下面两种方式均可实现:

objectClass.getDeclaredConstructor(String.class, int.class);
objectClass.getDeclaredConstructor(new Class[] { String.class, int.class });

具体代码实例如下:

Result<Object> objectResult = new Example<>();
Class<? extends Example> aClass = Example.getClass();
//获得所有构造方法
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();

Constructor类中提供的常用方法如图所示:

图片

具体实例如下:

Result<Object> objectResult = new Result<>();
Class<? extends Result> aClass = objectResult.getClass();
//获得所有构造方法
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
//Constructor类中提供的常用方法
for (Constructor<?> declaredConstructor : declaredConstructors) {
    declaredConstructor.setAccessible(true);
    Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
    Object o = declaredConstructor.newInstance();
    boolean varArgs = declaredConstructor.isVarArgs();
    Class<?>[] exceptionTypes = declaredConstructor.getExceptionTypes();
}

通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既能查看是否被指定的修饰符修饰,又能以字符串的形式获得所有修饰符。
Modifier类常用静态方法如图:

图片

例如,判断对象constructor所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下:

int modifiers = declaredConstructor.getModifiers();
boolean aPrivate = Modifier.isPrivate(modifiers);
String embellishment = Modifier.toString(modifiers);
4.访问成员变量

在通过下列一组方法访问成员变量时,将返回 Field 类型的对象或数组。每个 Field 对象代表一个成员变量,利用 Field 对象可以操纵相应的成员变量:

图片

如果是访问指定的成员变量,可以通过该成员变量的名称来访问。例如,访问一个名称为birthday的成员变量,访问方法如下:

object. getDeclaredField("birthday");

Field 类中提供的常用方法如下:

图片

User user = new User();
Class<? extends User> aClass = user.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
    declaredField.setAccessible(true);
    String name = declaredField.getName();
    Class<?> type = declaredField.getType();
    declaredField.set(user,1);
    Object o = declaredField.get(user);
}

注意:在反射权限为 private 和 protected 的成员变量时,需要执行 setAccessible()方法,并将入口参数设为 true,否则不允许访问。

5.访问成员方法

在通过下列一组方法访问成员方法时,将返回 Method 类型的对象或数组。每个 Method 对象代表一个方法,利用 Method 对象可以操纵相应的方法:

图片

如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如,访问一个名称为 print、入口参数类型依次为String型和int型的方法,通过下面两种方式均可实现:

objectClass.getDeclaredMethod("print", String.class, int.class);
objectClass.getDeclaredMethod("print", newClass[] {String.class, int.class });

Method类中提供的常用方法如图所示:

图片

具体示例代码如下:

User user = new User();
Class<? extends User> aClass = user.getClass();
Method[] methods = aClass.getMethods();
for (Method method : methods) {
    method.setAccessible(true);
    String name = method.getName();
    Parameter[] parameters = method.getParameters();
    Class<?> returnType = method.getReturnType();
    Class<?>[] exceptionTypes = method.getExceptionTypes();
    Object invoke = method.invoke(1);
    boolean varArgs = method.isVarArgs();
    int modifiers = method.getModifiers();
}

原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/81019.html

Like (0)
guozi的头像guozi
Previous 2024年5月31日 上午11:15
Next 2024年5月31日 上午11:19

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注