龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

在Java中使用反射分析类结构

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
首先要获取需要进行分析的类的名称,将类名称指定到Class类中的forName(String classname)方法为参数,调用该方法后将返回一个该指定类型的Class对象,Class对象描述了该类型的具体信息,其

  首先要获取需要进行分析的类的名称,将类名称指定到Class类中的forName(String classname)方法为参数,调用该方法后将返回一个该指定类型的Class对象,Class对象描述了该类型的具体信息,其中一些重要的方法包括:getFields(),getMethods(),getConstrUCtors()这些方法分别返回该类型中支持的公有字段,方法和构造器数组,其中包含超类的公有成员,而同是Class中以上的方法名称中加入了“Declared”的方法则返回该类型中定义的所有成员包括私有的但不包括超类成员,现在,我们已经获得了该类型的字段,方法和构造器数组,接着,我们使用Java.lang.reflect包中的Field,Method,Constructor类来获得字段,方法和构造器的具体信息,例如:我们要显示该类型中的所有的字段信息,伪代码:
  
  //getDeclaredFields返回所有定义的字段数组
  
  Field[] fields = Class.getDeclaredFields(); 
  
  for (i = 0; i < fields.length; i++)
  
  {
  
  Field f = fields[i];
  
  Class type = f.getType();  //getType()返回字段的数据类型
  
  String name = f.getName();  //getName()返回字段名称
  
  println(Modifier.toString(f.getModifiers()));
  
  //getModifiers()返回一个代表访问控制符的整数
  
  //Modifier.toString()将该整数转换为对应的访问控制符字符串
  
  println(" "+ type.getName() + " "+ name);
  
  //type.getName()返回数据类型名称
  
  }
  
  好了下面看一个完整的例子,例子长了一点不过很简单!
  
  import java.lang.reflect.*;
  import javax.swing.*;
  
  public class ReflectTest
  {
  public static void main(String[] args)
  {
  String name;
  if (args.length > 0)
  name = args[0];
  else
  name = JOptionPane.showInputDialog("输入一个类名:按(java.lang.Double)格式");
  
  try
  {
  Class cl = Class.forName(name);
  Class supercl = cl.getSuperclass(); //获得超类的Class对象
  System.out.println("class "+ name);
  //判定超类是否为空或为Object
  if (supercl != null && supercl != Object.class)
  System.out.println("extends "+ supercl.getName());
  
  System.out.print(" { ");
  printConstructors(cl);
  System.out.println();
  printMethods(cl);
  System.out.println();
  printField(cl);
  System.out.println("}");
  }
  //当使用class对象时注重捕捉该异常,异常为类型未创建
  catch(ClassNotFoundException e)
  {
  e.printStackTrace();
  System.out.println("类型未创建");
  }
  System.exit(0);
  }
  
  /**
   *该方法打印构造器的具体信息
   */
  public static void printConstructors(Class cl)
  {
  //定义构造器数组
  Constructor[] constructors = cl.getDeclaredConstructors();
  
  for (int i = 0; i < constructors.length; i++)
  {
  //将数组元素赋给一个构造器对象
  Constructor constr = constructors[i];
  String name = constr.getName(); //获取构造器名称
  //打印访问修饰符
  System.out.print(Modifier.toString(constr.getModifiers()));
  System.out.print(" "+ name + "(");
  
  /**
   *定义一个参数类型数组该数组是Class对象
   *getParameterTypes()返回该构造器参数类型的数组
   *打印参数类型名称
   */
  Class[] paramTypes = constr.getParameterTypes();
  for (int j = 0; j < paramTypes.length; j++)
  {
  if (j > 0) System.out.print(", ");
  System.out.print(paramTypes[j].getName());
  }
  System.out.println(");");
  }
  }
  
  /**
   *该方法打印方法的具体信息
   */
  public static void printMethods(Class cl)
  {
  Method[] methods = cl.getDeclaredMethods();
  
  for (int i = 0; i < methods.length; i++)
  {
  Method m = methods[i];
  Class retType = m.getReturnType();
  String name = m.getName();
  
  System.out.print(Modifier.toString(m.getModifiers()));
  System.out.print(" "+ retType.getName() +" "+ name + "(");
  
  Class[] paramTypes = m.getParameterTypes();
  for (int j = 0; j < paramTypes.length; j++)
  {
  if (j > 0) System.out.print(", ");
  System.out.print(paramTypes[j].getName());
  }
  System.out.println(");");
  }
  }
  
  /**
   *该方法打印字段的具体信息
   */
  public static void printField(Class cl)
  {
  Field[] fields = cl.getDeclaredFields();
  
  for (int i = 0; i < fields.length; i++)
  {
  Field f =fields[i];
  Class type = f.getType();
  String name = f.getName();
  System.out.print(Modifier.toString(f.getModifiers()));
  System.out.println(" "+ type.getName() +" "+ name + ";");
  }
  }
  }
  
  我经常碰到这样的问题:比如当我要写一个接受命令行参数的程序时我通常是先打开NetBeans工具,写完并保存后有回到命令提示符上使用javac编译java运行,为什么?因为用开发环境运行的话接收不了命令行参数而会抛出一个异常,我是不是很蠢,其实用一个JOptionPane.showInputDialog可以避免发生这样的事情,只需加一个判定,我们编程的良好风格是多关心如何编写稳重的代码,而不是动不动就捕捉异常!
  
精彩图集

赞助商链接