反射
作用:
-
-
在运行时查看对象
-
实现通用的数组操作代码
- 利用 Method 对象
一、Class
在程序运行期间,Java 运行时系统始终为所有对象维护一个运行时(runtime)的类型标识,这个信息跟踪着每个对象所属的类,虚拟机会利用运行时类型信息选择相应的方法执行。Class 类保存了这些信息,可以用 Object 中定义的 getClass 方法得到一个 Class 对象,这个对象表示一个特定类的属性。
用 getName 方法返回类的名字:
Employee e = new Employee("Babara", ...); System.out.println(e.getClass().getName() + ": " + e.getName()); // Employee: Babara
用静态方法 forName 可以获得类名对应的 Class 对象:
String className = "java.util.Random";
Class cl = Class.forName(className);
一个 Class 对象实际上表示的是一个类型(未必是一个类),假设 T 是任意的 Java 类型,则 T.class 代表对应的 Class 对象:
Class cl1 = Random.class; Class cl2 = int.class; Class cl3 = Double[].class; // ...
虚拟机为每个类型管理一个 Class 对象,因此可以利用 == 运算符进行比较:
if (e.getClass() == Employee.class) // ...
用 newInstance 方法可以动态地创建一个类的实例(如果这个类没有无参数的构造器,则抛出异常):
String str = "java.util.Random"; Object m = Class.forName(str).newInstance(); // m = new Random();
Class 类实际上是一个泛型类。
API - java.lang.Class
-
-
getName
-
newInstance
- getField
-
getFields / getMethods / getConstructors
- getDeclareFields / getDeclareMethods / getDeclareConstructors
二、检查类的结构
java.lang.reflect 包中有三个类 Field、Method、Constructor 分别用于描述类的域、方法、构造器,还有 Modifier 用于反映方法或构造器的修饰符。
API - java.lang.reflect.Constructor
-
-
getExceptionTypes
-
getModifiers
- getName
-
getParameterTypes
- getReturnType
下面是书中一个测试 demo ,输入类名,能够输出这个类所有域名以及方法和构造器的签名:
import java.util.*; import java.lang.reflect.*; public class ReflectionTest { public static void main(String[] args) { // 读取类名 String name; if (args.length > 0) { name = args[0]; } else { Scanner in = new Scanner(System.in); System.out.println("输入类名(如:java.util.Data):"); name = in.next(); } // 打印类名和超类名 try { Class cl = Class.forName(name); Class supercl = cl.getSuperclass(); String modifiers = Modifier.toString(cl.getModifiers()); if (modifiers.length() > 0) { System.out.print(modifiers + " "); } System.out.print("class " + name); if (supercl != null && supercl != Object.class) { System.out.print(" extends " + supercl.getName()); }
System.out.print(" {\n"); printFields(cl); System.out.println(); printConstructors(cl); System.out.println(); printMethods(cl); System.out.println("}"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.exit(0); } public static void printFields(Class cl) { Field[] fields = cl.getDeclaredFields(); for (Field f : fields) { Class type = f.getType(); String name = f.getName(); System.out.print("\t"); String modifiers = Modifier.toString(f.getModifiers()); if (modifiers.length() > 0) { System.out.print(modifiers + " "); } System.out.println(type.getName() + " " + name + ";"); } } public static void printConstructors(Class cl) { Constructor[] constructors = cl.getDeclaredConstructors(); for (Constructor c : constructors) { String name = c.getName(); System.out.print("\t"); String modifiers = Modifier.toString(c.getModifiers()); if (modifiers.length() > 0) { System.out.print(modifiers + " "); } System.out.print(name + " "); printParameters(c.getParameterTypes()); } } public static void printMethods(Class cl) { Method[] methods = cl.getDeclaredMethods(); for (Method m : methods) { Class retType = m.getReturnType(); String name = m.getName(); System.out.print("\t"); String modifiers = Modifier.toString(m.getModifiers()); if (modifiers.length() > 0) { System.out.print(modifiers + " "); } System.out.print(retType.getName() + " " + name); printParameters(m.getParameterTypes()); } } public static void printParameters(Class[] paramTypes) { System.out.print("("); for (int i = 0; i < paramTypes.length; i++) { if (i > 0) { System.out.print(", "); } System.out.print(paramTypes[i].getName()); } System.out.println(");"); } }
运行情况: