概要
反射是指能够分析类能力的程序,也称为程序运行时的自省能力,主要用于工具程序的构造,而非应用程序。
反射机制的作用包括以下四点:
- 运行时分析类
- 运行时查看对象
- 实现通用数组操作
- 利用Method
Java的反射机制主要通过以下几个类实现:Class、Constructor
相关类、方法
Class
Class(代表类型的类,实际是一个泛型类,但平时使用时可忽略类型参数,直接使用原始Class类):如何获得Class对象呢?可通过任意Java类型(或void)的class方法获取,或者是通过对象的getClass方法获得。
常用方法包括:
- getName
- forName-静态工厂方法,获得指定类名对应的Class对象
- newInstance-获得Class表示类型的对象
- getFields、getMethods、getConstructor(公有域或方法)
- getDeclaredFie1ds、getDeclareMethods、getDeclaredConstructors(全部域或方法,但不包括继承而来的)
Field、Method、Constructor
通用方法
- getName
- getModifiers–Modifier.toString
- setAccessible–可在运行时修改成员的访问限制
Field
- getType
- get、set
Method
- invoke
《Java核心技术-卷一》中应用的典型事例是使用反射机制实现解析打印类的成员。代码示例如下:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
/**
* @description: this program uses reflection to print all features of a class
* @author: lyg89
* @create: 2019-03-23 23:10
**/
public class ReflectionTest {
public static void main(String[] args) {
String name;
if (args.length > 0) {
name = args[0];
} else {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date):");
name = scanner.next();
}
try {
Class<?> aClass = Class.forName(name);
String modifiers = Modifier.toString(aClass.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.print("class " + name);
Class<?> superclass = aClass.getSuperclass();
if (superclass != null && superclass != Object.class) {
System.out.print(" extends " + superclass.getName());
}
System.out.print("\n{\n");
printConstructors(aClass);
System.out.println();
printMethods(aClass);
System.out.println();
printFields(aClass);
System.out.println("}");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
}
private static void printConstructors(Class clazz) {
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.print(" ");
int modifiers = constructor.getModifiers();
String strModifier = Modifier.toString(modifiers);
if (strModifier.length() > 0) {
System.out.print(strModifier + " ");
}
System.out.print(clazz.getName() + " (");
Class[] parameterTypes = constructor.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(parameterTypes[i].getName());
}
System.out.println(");");
}
}
private static void printMethods(Class clazz) {
for (Method method : clazz.getMethods()) {
System.out.print(" ");
int modifiers = method.getModifiers();
String strModifier = Modifier.toString(modifiers);
if (strModifier.length() > 0) {
System.out.print(strModifier + " ");
}
Class<?> returnType = method.getReturnType();
System.out.print(returnType.getName() + " " + method.getName() + " (");
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(parameterTypes[i].getName());
}
System.out.println(");");
}
}
private static void printFields(Class clazz) {
for (Field field : clazz.getFields()) {
System.out.print(" ");
int modifiers = field.getModifiers();
String strModifier = Modifier.toString(modifiers);
if (strModifier.length() > 0) {
System.out.print(strModifier + " ");
}
System.out.println(field.getType().getName() + " " + field.getName() + ";");
}
}
}
小结
反射机制帮助我们在程序运行时可以访问程序的元信息,包括Java类型、对象、方法等,并可以动态的创建对象,甚至修改对象的访问控制限制,但是在Java 9中的模块机制,开始对setAccessible有一些限制。利用反射机制,我们可以构造强大的工具集,因此在很多框架中都有应用,可以说理解了反射,对程序的设计所追求的灵活性会有更深刻的认识。