利用 反射 检查类的结构 Class类和java.lang.reflect包的使用 ( 含demo )

先上运行效果:  输入我们想分析检查的类(全类名, 带包名), 以java.lang.Double为例

利用 反射 检查类的结构 Class类和java.lang.reflect包的使用 ( 含demo )_第1张图片利用 反射 检查类的结构 Class类和java.lang.reflect包的使用 ( 含demo )_第2张图片

可以看到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:

利用 反射 检查类的结构 Class类和java.lang.reflect包的使用 ( 含demo )_第3张图片

可以看到只返回了公有成员, 连Son的默认成员都没有,更别说私有的了

同样需要注意的是 ,返回的不止有Father类和Son类的成员, 还有Object类的成员(wait(),notify().......), 也就是说上述的"父类"不单单指直接父亲, 而是家族树向上一直到Object类(JAVA所有类的祖宗!), Father没有显式继承所以Father默认继承了Object, 否则返回的包含Son, Father, Fahter的父类, Fahter的父类的父类.....Object类的所有公有成员

怎么样,就问你可怕不可怕??? 

有人会说: 这样也只是能看到结构而已, 又有什么用呢,所以上面说了, 搭配代理使用更可怕!

你可能感兴趣的:(JAVA)