利用Java的反射机制可以对Java类进行解析。本程序以类名为输出参数,输出该类的名称、继承的父类、实现的接口、包含的域、拥有的构造器以及方法,以及该类的继承链。
代码如下:
package chapter5;
import java.util.*;
import java.lang.reflect.*;
/**
* This program uses reflection to print all features of a class.
*
* @version 1.1 2016-12-05
* @author Zhang Yufei
*
*/
public class ReflectionTest {
@SuppressWarnings("rawtypes")
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 scan = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date):");
name = scan.next();
scan.close();
}
try {
// print class name and super class name (if != object)
Class cl = Class.forName(name);
Class supercl = cl.getSuperclass();
Class[] interfaces = cl.getInterfaces();
String modifiers = Modifier.toString(cl.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers);
}
// is class or interface
if (!cl.isInterface()) {
System.out.print(" class ");
}
printType(cl);
if (supercl != null && supercl != Object.class) {
System.out.print(" extends ");
printType(supercl);
}
if (interfaces.length > 0) {
System.out.print(" implements ");
for (int j = 0; j < interfaces.length; j++) {
if (j > 0) {
System.out.print(", ");
}
printType(interfaces[j]);
}
}
System.out.print(" {\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
printExtendsChain(cl);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
}
/**
* Prints all constructors of a class
*
* @param cl
* a class
*/
@SuppressWarnings("rawtypes")
private static void printConstructors(Class cl) {
Constructor[] constructors = cl.getDeclaredConstructors();
for (Constructor c : constructors) {
String name = c.getName();
System.out.print(" ");
// print modifiers.
String modifiers = Modifier.toString(c.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
// print name and parameter types.
System.out.print(name.substring(name.lastIndexOf(".") + 1) + " (");
Class[] paramTypes = c.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) {
System.out.print(", ");
}
printType(paramTypes[j]);
}
System.out.print(")");
// print exceptions
Class[] exceptions = c.getExceptionTypes();
if (exceptions.length > 0) {
System.out.print(" throws ");
for (int j = 0; j < exceptions.length; j++) {
if (j > 0) {
System.out.print(", ");
}
printType(exceptions[j]);
}
}
System.out.println(";");
}
}
/**
* Prints all methods of a class
*
* @param cl
* a class
*/
@SuppressWarnings("rawtypes")
private static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
Class retType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
// print modifiers, return type and method name
String modifiers = Modifier.toString(m.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
printType(retType);
System.out.print(" " + name + "(");
// print parameter types
Class[] paramTypes = m.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) {
System.out.print(", ");
}
printType(paramTypes[j]);
}
System.out.print(")");
// print exceptions
Class[] exceptions = m.getExceptionTypes();
if (exceptions.length > 0) {
System.out.print(" throws ");
for (int j = 0; j < exceptions.length; j++) {
if (j > 0) {
System.out.print(", ");
}
printType(exceptions[j]);
}
}
System.out.println(";");
}
}
/**
* Prints all fields of a class
*
* @param cl
* a class
*/
@SuppressWarnings("rawtypes")
private static void printFields(Class cl) {
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
Class type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
printType(type);
System.out.println(" " + name + ";");
}
}
/**
* Prints a type.
*
* @param type
* a type.
*/
@SuppressWarnings("rawtypes")
private static void printType(Class type) {
String name = type.getName();
if (name.startsWith("[")) {
if (name.startsWith("[C")) {
System.out.print("char[]");
} else if (name.startsWith("[B")) {
System.out.print("byte[]");
} else if (name.startsWith("[S")) {
System.out.print("short[]");
} else if (name.startsWith("[I")) {
System.out.print("int[]");
} else if (name.startsWith("[J")) {
System.out.print("long[]");
} else if (name.startsWith("[F")) {
System.out.print("float[]");
} else if (name.startsWith("[D")) {
System.out.print("double[]");
} else if (name.startsWith("[Z")) {
System.out.print("boolean[]");
} else if (name.startsWith("[L")) {
System.out.print(name.substring(name.lastIndexOf(".") + 1, name.length() - 1)
+ "[]");
}
} else {
System.out.print(name.substring(name.lastIndexOf(".") + 1));
}
}
/**
* Prints the extends chain for a class
*
* @param cl
* a class
*/
@SuppressWarnings("rawtypes")
public static void printExtendsChain(Class cl) {
System.out.print("\n\nExtends chain:\n ");
printType(cl);
Class superclass = cl.getSuperclass();
while (superclass != Object.class) {
System.out.print(" --> ");
printType(superclass);
superclass = superclass.getSuperclass();
}
System.out.print(" --> ");
printType(superclass);
}
}
需要注意是:
① 如果输入的是一个接口,调用getModifiers方法后得到结果会输出interface关键字,如果是普通类,则需要手动编写代码输出class关键字。可以用isInterface方法检测输入是否为一个接口。
② Java默认的代码对于数组类型的名称显示为乱码,因此,笔者加入一个printType方法来显示数据类型的名称。
③ 默认显示的类名称包含类所在的包名,笔者通过substring方法将包名删去,仅显示类名。
例如:输入:java.lang.String,则显示下面的内容:
public class BufferedInputStream extends FilterInputStream {
public BufferedInputStream (InputStream);
public BufferedInputStream (InputStream, int);
public synchronized int read(byte[], int, int) throws IOException;
public synchronized int read() throws IOException;
public void close() throws IOException;
private void fill() throws IOException;
public synchronized int available() throws IOException;
public synchronized void mark(int);
public boolean markSupported();
public synchronized void reset() throws IOException;
public synchronized long skip(long) throws IOException;
private byte[] getBufIfOpen() throws IOException;
private InputStream getInIfOpen() throws IOException;
private int read1(byte[], int, int) throws IOException;
private static int DEFAULT_BUFFER_SIZE;
private static int MAX_BUFFER_SIZE;
protected volatile byte[] buf;
private static final AtomicReferenceFieldUpdater bufUpdater;
protected int count;
protected int pos;
protected int markpos;
protected int marklimit;
}
Extends chain:
BufferedInputStream --> FilterInputStream --> InputStream --> Object