先上运行效果: 输入我们想分析检查的类(全类名, 带包名), 以java.lang.Double为例
可以看到Double类的结构一览无余,无论公有私有 是否为final和static, 即使native的本地方法都被我们的火眼金睛发现了, 这就是java反射机制的威力, 其实更可怕的是反射不仅仅用于编译程序时可以使用的类, 更多的是在程序运行的时候动态地分析类的结构并创建实例, 再通过代理机制与之配合, (这也就是java框架的核心机制) 所以java.lang.reflect包是开发人员的利器啊!
看到效果了, 那我们的反射到底怎么用呢? java.lang.reflect包又有啥工具呢?
在java.lang.reflect包中有三个类Field, Method, Contructor分别用于描述类的域, 方法和构造器
Field类中有一个getType方法,用来返回描述域所属类型的Class对象。
Method 和 Contructor 类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法
三个类都有一个叫做getModifiers的方法, 它将返回一个整形数值, 用不同的位开关描述public和static 这样的描述符的使用情况
另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers()返回的整形数值。
例如,可以使用Modifier类中的isPublic 、isPrivate 、或isFinal判断方法或者构造器是否是public、private或者final。
我们需要做的全部工作就是调用Modifier类中的相应方法,并对返回的整型数值进行分析,另外,还可以利用Modifier.toString 方法 将修饰符打印出来。
Class类中的getFields,getMethods和getContructors 方法将分别返回类提供的public域,方法,和构造器数组,其中包括超类的公有成员。
Class类的getDeclareFields、getDeclareMethods和getDeclareContructors 方法将分别返回类中声明的全部域、方法和构造器,其中包括私有的和受保护的成员,但不包括超类的成员。
我们的demo源码:
package test;
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) {
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 {
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.println("\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);
}
public static void printConstructors(Class cl){
Constructor[] constructors=cl.getDeclaredConstructors();
//Declared
for(Constructor c:constructors)
{
String name=c.getName();
System.out.print(" ");
String modifiers=Modifier.toString(c.getModifiers());
if(modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.print(name+"(");
Class[] paramTypes=c.getParameterTypes();
for(int j=0;j0)
System.out.print(",");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
public static void printMethods(Class cl)
{
//Method[] methods= cl.getMethods();
Method[] methods= cl.getDeclaredMethods();
for(Method m:methods)
{
Class retType= m.getReturnType();
String name=m.getName();
System.out.print(" ");
String modifiers=Modifier.toString(m.getModifiers());
if(modifiers.length()>0)
System.out.print(modifiers +" ");
System.out.print(retType.getName()+" "+name+"(");
Class[] paramTypes=m.getParameterTypes();
for(int j = 0;j0)
System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
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(" ");
String modifiers=Modifier.toString(f.getModifiers());
if(modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+name+";");
}
}
}
上面的demo用的是getDeclareFields、getDeclareMethods和getDeclareContructors方法, 包含本类的私有和受保护成员, 但不包括其父类成员, 我们把上述demo的 对应方法全换成getFields,getMethods和getContructors看看效果:
因为Double的成员太多了, 带上父类成员就更多了, 为了清晰,我又写了一个父类和子类做例子:
父类是这样式儿的:
package test;
public class Father
{
public int father_public_field;
int father_default_field;
public Father() {
}
public void father_public_method() {
}
private void father_private_method() {
}
}
子类是这样式儿的:
package test;
public class Son extends Father
{
public int son_public_field;
int son_default_field;
}
简单吧, 注意两个类的修饰符, 我们把上面的demo对应方法换成getFields,getMethods和getContructors:
可以看到只返回了公有成员, 连Son的默认成员都没有,更别说私有的了
同样需要注意的是 ,返回的不止有Father类和Son类的成员, 还有Object类的成员(wait(),notify().......), 也就是说上述的"父类"不单单指直接父亲, 而是家族树向上一直到Object类(JAVA所有类的祖宗!), Father没有显式继承所以Father默认继承了Object, 否则返回的包含Son, Father, Fahter的父类, Fahter的父类的父类.....Object类的所有公有成员
怎么样,就问你可怕不可怕???
有人会说: 这样也只是能看到结构而已, 又有什么用呢,所以上面说了, 搭配代理使用更可怕!