一.原理
简而言之,反射机制是指程序可以在运行时获取自己的信息。 如果您知道类的名称/实例对象,则可以找到该类的所有方法和变量的信息(包括方法名称、变量名、方法、修饰符、类型和方法参数等所有信息)。 如果明确知道此类中某个方法名称参数的个数类型,也可以通过传递参数来执行该类中的该方法。 这就是反射。
虽然Java不是动态语言,但它有一个非常突出的动态机制: Reflection。 这样,在编译过程中就可以在运行时加载、探测和使用完全未知的classes。 也就是说,Java程序在运行时加载第一个识别名称的类,识别其完整结构(但methods定义除外),生成该对象实体,为其fields设置值,或调用methods 是“看穿类”的能力。
当然,在日常编程中很少使用反射,但在创建框架时会经常使用反射。 例如,虽然使用某个类进行操作,但由于该类是由用户在配置文件中配置的,因此必须首先阅读配置文件以获得该类的所有类名。 例如,使用test.Person,使用反射API进行操作。
二.优缺点
反射的优点当然体现在其动态性上,就是可以在运行时确定类型并绑定对象。 动态编译最大限度地发挥java的灵活性,体现多态性的应用,降低类间的耦合性。 总之,反射机制的优点是能够实现对象的动态创建和编译,特别是在J2EE的开发中,其灵活性尤为突出。 例如,大型软件不能一次完美地设计。 当发现此程序已编译并发布,并且需要更新某些功能时,用户无法卸载以前的版本并重新安装新版本。 如果是这样的话,这个软件肯定没人用。 如果是静态的,则必须重新编译整个程序才能实现功能更新,但反射机制允许在运行时动态创建,而无需卸载
和编译,可以实现这个功能。
其缺点是影响性能。 使用反射基本上是一种解释操作,我们可以告诉JVM我们想做什么,以及它是否满足我们的要求。 这样的操作总是比直接执行相同的操作慢。
三、利用反射实现类文件的逆编译
打包工具;
import Java.lang.reflect.constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import Java.lang.reflect.modifier;
import test.Person; //导入测试类文件
公共类反射测试{
publicstaticvoidmain (字符串[ ] args ) {
类c=null;
try {
//基于传递的类的全名创建Class对象。 注意必须是全名
c=class.forname(test.Person );
//获取数据包路径
system.out.println (package (c.get package ).getName ) ); n ';
//得到类修饰符
system.out.print (modifier.tostring ) c.getmodifiers ();
//得到类名
system.out.print (' class ' c.getsimplename ) );
//得到父类名
system.out.print (extends ' c.get super class ().getSimpleName ) );
//得到类实现的接口数组
Class[] inters=c.getInterfaces (;
if(Inters.Length0) {
system.out.print(implements );
for(intI=0; i inters.length; I ) {
system.out.print (inters [ I ].getsimplename ();
if(Iinters.Length-1 ) {
System.out.print (',');
}
}
}
system.out.println('{};
//获取类属性
打印机字段(c;
//获取类生成器
打印构造器(c;
获取//类方法
打印方法(c;
system.out.println('};
}catch(classnotfoundexceptione ) )
e .打印堆栈跟踪(;
>}
}
private static void printConstructor(Class c){
Constructor[] cs = c.getConstructors();
for (int i = 0; i < cs.length; i++) {
System.out.println();
System.out.print("t");
// 得到整数形式构造函数修饰符,使用Modifier进行解码
System.out.print(Modifier.toString(cs[i].getModifiers()) + " ");
// 得到方法名
System.out.print(cs[i].getName() + "(");
// 得到方法参数数组
Class[] paras = cs[i].getParameterTypes();
for (int j = 0; j < paras.length; j++) {
System.out.print(paras[j].getSimpleName() + " arg" + j);
if (j < paras.length - 1) {
System.out.print(", ");
}
}
System.out.print(")");
System.out.println(" {");
System.out.println("tt\\方法体");
System.out.println("t}");
}
}
private static void printField(Class c) {
// 得到属性数组
Field[] fs = c.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
System.out.print("t");
// 得到整数形式属性修饰符,使用Modifier进行解码
System.out.print(Modifier.toString(fs[i].getModifiers()) + " ");
// 得到属性类型
System.out.print(fs[i].getType().getSimpleName() + " ");
// 得到属性名
System.out.println(fs[i].getName() + ";");
}
}
public static void printMethods(Class c) {
// 得到方法数组
Method[] md = c.getMethods();
for (int i = 0; i < md.length; i++) {
System.out.println();
System.out.print("t");
// 得到整数形式方法修饰符,使用Modifier进行解码
System.out.print(Modifier.toString(md[i].getModifiers()) + " ");
// 得到方法返回类型
System.out.print(md[i].getGenericReturnType() + " ");
// 得到方法名
System.out.print(md[i].getName() + "(");
// 得到方法参数数组
Class[] paras = md[i].getParameterTypes();
for (int j = 0; j < paras.length; j++) {
System.out.print(paras[j].getSimpleName() + " arg" + j);
if (j < paras.length - 1) {
System.out.print(", ");
}
}
System.out.print(")");
// 得到抛出的异常类数组
Class[] exceps = md[i].getExceptionTypes();
if (exceps.length > 0) {
System.out.print(" throws ");
for (int k = 0; k < exceps.length; k++) {
System.out.print(exceps[k].getSimpleName());
if (k < exceps.length - 1) {
System.out.print(", ");
}
}
}
System.out.println(" {");
System.out.println("tt\\方法体");
System.out.println("t}");
}
}
}
文章来源:guntong