这是《Java核心技术 卷I》用反射打印一个类的全部信息的全部代码,后续将会拆解这些代码
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
public class ReflectionTest {
public static void main(String[] args) {
// read class name from command line args or user input
String name;
if (args.length > 0)
name = args[0];
else {
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date)");
name = in.next();
}
try {// print class name and super class name(if !=Object)
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{\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
}
// prints all constructor of a class
public static void printConstructors(Class cl) {
Constructor[] constructor = cl.getDeclaredConstructors();
for (Constructor c : constructor) {// 构造器由 “修饰符 + 名字 + 参数 ” 组成
String modifiers = Modifier.toString(c.getModifiers());
String name = c.getName();
System.out.println("Constructors:");
if (modifiers.length() > 0)
System.out.print(modifiers + " ");
System.out.print(name + "(");
// print parameter types
Class[] paramTypes = c.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0)
System.out.print(",");
System.out.print(paramTypes[i].getName());
}
System.out.print(");");
System.out.println();
System.out.println();
}
}
// print all methods of a class
public static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
String modifier = Modifier.toString(m.getModifiers());
Class retType = m.getReturnType();
String name = m.getName();
System.out.println("Methods:");
// print modifiers,returnType and method name
if (modifier.length() > 0)
System.out.print(modifier + " ");
System.out.print(retType + " " + name + "(");
// print parameter types
Class[] parameters = m.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
if (i > 0)
System.out.print(",");
System.out.print(parameters[i].getName());
}
System.out.println(")");
System.out.println();
}
}
// print all fields of a class
public static void printFields(Class cl) {
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
Class type = f.getType();
String name = f.getName();
System.out.println("Fields:");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length() > 0)
System.out.print(modifiers + " ");
System.out.print(type.getName() + " " + name + ";");
System.out.println();
}
}
}
首先,类的信息有类名,有没有父类,有成员变量,有构造方法,有成员方法。而 ,
成员变量 = 修饰符 + 域类型 + 名字 (private String name)
构造方法 = 修饰符 + 名字 + 参数(public Student(String name, int age))参数的括号,逗号是排版问题了,正是因为这个排版问题,输出参数的时候用 foreach 语句比较难排版,所以用了for语句。
成员方法 = 修饰符 + 返回值 + 名字 + 参数
其实处理这些信息操作基本上是一样的
比如:xxx是一个field[ ],Constructor[ ] 或者Method[ ] 的对象,在用增强for遍历他们的时候(假设遍历的符号x),
修饰符 : String modifiers = Mofier.toString(x.getModifiers);
x.getModifiers返回一个 int 的数值,而ModiMofier.toString这个静态方法可以根据这个数值返回修饰符的信息。因为修饰符是可能没有的,所以要用if(modifiers.length() > 0)来判断有没有修饰符,有就打印,没有就不打印
名字 : String name = x.getName();
Field,Method,Constructor 这三个类都有getName方法,用来返回项目名称。
另外提的是Clas类中也有一个getName方法,这个方法返回的是类的名字。
参数 :
Class[] paramTypes = c.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0)
System.out.print(",");
System.out.print(paramTypes[i].getName());
paramTypes是Class[ ]的数组,循环输出里面每一个“类”的名字,就用到了Class类的getName方法了
(成员/构造)方法参数,成员类型,方法返回类型,这三个都是返回一个Class对象(参数是对象数组),想要把他们打印出来,就要用 getName来返回他们的名字
下面看打印构造方法的printConstructors方法
// prints all constructor of a class
public static void printConstructors(Class cl) {
Constructor[] constructor = cl.getDeclaredConstructors();
for (Constructor c : constructor) {// 构造器由 “修饰符 + 名字 + 参数 ” 组成
String modifiers = Modifier.toString(c.getModifiers());
String name = c.getName();
System.out.println("Constructors:");
if (modifiers.length() > 0)
System.out.print(modifiers + " ");
System.out.print(name + "(");
// print parameter types
Class[] paramTypes = c.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0)
System.out.print(",");
System.out.print(paramTypes[i].getName());
}
System.out.print(");");
System.out.println();
System.out.println();
}
}
1.无论是成员变量,构造器,还是成员方法,都是可以用private修饰的,所以定义他们的对象的时候一定要用getDeclaredXXXX(访问全部方法/成员)
2.Constructor[ ] 接收了一堆构造器方法,要遍历它,最简单的就是用增强for
3.因为增强for遍历的时候,需要输出这个构造器的信息,所以在每个构造器的名字,修饰符,参数,应该在增强for里面创建。而参数正好又是Class[ ] 接收的一个数组,于是又可以使用for语句遍历,不用增强for是因为增强for很难排版到我们想要的格式
一样的来看打印成员方法的printMethods方法
public static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
String modifier = Modifier.toString(m.getModifiers());
Class retType = m.getReturnType();
String name = m.getName();
System.out.println("Methods:");
// print modifiers,returnType and method name
if (modifier.length() > 0)
System.out.print(modifier + " ");
System.out.print(retType + " " + name + "(");
// print parameter types
Class[] parameters = m.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
if (i > 0)
System.out.print(",");
System.out.print(parameters[i].getName());
}
System.out.println(")");
System.out.println();
}
}
1.定义Mehod[ ] 对象并且遍历他
2.各要素的创建,排版
3.留意的地方:修饰符打印要通过if (modifier.length() > 0)这条语句判断,因为可能存在没有修饰符的情况,不能瞎打印
不要忘了参数 parameters 是一个数组,每一个方法的参数都放在里面,遍历他们并通过parameters[i].getName()来获取他们的名字
下面是打印成员变量的printFields方法
public static void printFields(Class cl) {
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
Class type = f.getType();
String name = f.getName();
System.out.println("Fields:");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length() > 0)
System.out.print(modifiers + " ");
System.out.print(type.getName() + " " + name + ";");
System.out.println();
}
}
1.和成员方法不同,成员方法用getReturnType()返回一个返回类型,成员变量的域类型是通过getType()返回的,一样的是返回一个Class对象,所以也是要用getName来获取它的类型名字
最后是main方法
public static void main(String[] args) {
// read class name from command line args or user input
String name;
if (args.length > 0)
name = args[0];
else {
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date)");
name = in.next();
}
try {// print class name and super class name(if !=Object)
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{\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
}
1.从控制台输入或者用户输入”包名 + 类名“来创建一个字符串,用于后面建立Class对象
2.查找它有没有父类,判断条件,这个父类不为空,而且不是Object类,Object类不算,他是所有类的父类
3.打印这个类的名字等信息(修饰符,类名,继承谁),类不一定都是public,所以依旧要判断有没有修饰符,就是有修饰符都要想到判断吧,有Class要想到用getName获取他们的名字