65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Java 中使用内省

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (2投票s)

2011年8月2日

CPOL

1分钟阅读

viewsIcon

44280

downloadIcon

606

本文描述了如何在 Java 中使用内省获取类的内部细节。

引言

内省是 Java 语言的一项重要特性。 使用内省,我们可以在运行时获取类的内部信息。 这些信息包括方法、字段、构造函数等。 内省的一个用途是在开发使用插件的应用程序中。 应用程序可以确定插件类的构造函数、方法和字段,并在运行时使用这些信息。 内省的其他用途包括创建 Java Bean 和开发 Javadoc。

背景

可以使用 java.lang.Class 类的 forName() 方法获取要内省的类。 我们可以使用 java.lang.ClassgetMethods() 方法获取类中所有方法的一个数组。 类似地,我们可以使用 getConstructors()getFields() 方法分别获取所有构造函数和字段。 可以使用 MethodConstructor 类的 getParameterTypes() 方法获取方法和构造函数的参数。

Using the Code

在代码中,我创建了一个 GUI,包含一个 TextField 项来接受要内省的类名,以及三个 JList 项来显示该类的所有方法、字段和构造函数。

lblClassName=new JLabel("Enter a class name: ");
txtClassName=new JTextField(20);
// For accepting class name

// For listing methods
lstMethods=new JList();
// For listing fields
lstFields=new JList();
// For listing constructors
lstConstructors=new JList();
lstMethods.setToolTipText("Methods");
lstFields.setToolTipText("Fields");
lstConstructors.setToolTipText("Constructors"); 

// Adding panels to frame
getContentPane().add(panelInput,"North");
getContentPane().add(panelOutput,"Center");

// Adding controls to panels
panelInput.add(lblClassName);
panelInput.add(txtClassName);
panelInput.add(btnIntrospect);
JScrollPane pane1=new JScrollPane(lstMethods);
panelOutput.add(pane1);
JScrollPane pane2=new JScrollPane(lstFields);
panelOutput.add(pane2);
JScrollPane pane3=new JScrollPane(lstConstructors);
panelOutput.add(pane3);

以下是 actionPerformed 方法的实现

public void actionPerformed(ActionEvent e)
{
 if(e.getSource()==txtClassName||e.getSource()==btnIntrospect)
 {
    if(txtClassName.getText().trim().length()==0)
    // Show error if class name not entered
    {
       JOptionPane.showMessageDialog(this,
         "Please enter a Class or Interface name","Error",
         JOptionPane.ERROR_MESSAGE);
       return;
    }
    try
    {
       Class c=Class.forName(txtClassName.getText());
       // Get class name entered by user

以下是如何获取方法信息

// Get all methods
Method[] methods=c.getMethods();
StringBuffer buffer=new StringBuffer();
// Create a string buffer to store method names to be displayed in JList
if(methods.length>0)
{
   // Get the first method
   Method m=methods[0];
   // Find return type of the method
   String t=m.getReturnType().toString();
   if(t.startsWith("class"))
   {
      t=t.substring(6);
      // Remove the leading word "class"
   }
   buffer.append(t+" "+m.getName()+"("+params(m)+")");
   // Add method names to string buffer.
   // The user-defined params() method returns parameters of the function.
}
int ctr=1;
while(ctr<methods.length)
// Repeat same process for all methods
{
   Method m=methods[ctr];
   String t=m.getReturnType().toString();
   if(t.startsWith("class"))
   {
      t=t.substring(6);
   }
   // Add all method names to the string buffer separated with ";"
   buffer.append(";"+t+" "+m.getName()+"("+params(m)+")");               
   ctr++;
}
lstMethods.setListData(buffer.toString().split(";"));
// Split method names and display them on JList

获取字段信息如下

Field[] fields=c.getFields(); // Get all fields
buffer=new StringBuffer();
if(fields.length>0)
{
   // Get the first field
   Field f=fields[0];
   // Find data type of the field 
   String t=f.getGenericType().toString();
   if(t.startsWith("class"))
   {
      t=t.substring(6);
   }
   buffer.append(t+" "+f.getName());
}
ctr=1;
while(ctr<fields.length)
// Repeat same process for all fields
{
   Field f=fields[ctr];
   String t=f.getGenericType().toString();
   if(t.startsWith("class"))
   {
      t=t.substring(6);
   }
   buffer.append(";"+t+" "+f.getName());
   // Add all field names to the string buffer separated with ";"

   ctr++;
}
lstFields.setListData(buffer.toString().split(";"));
// Split field names and display them on JList

这是我们获取构造函数信息的方式

    // Get all constructors
    Constructor[] constructors=c.getConstructors();
    buffer=new StringBuffer();
    if(constructors.length>0)
    {
       // Get the first constructor
       Constructor s=constructors[0];
       buffer.append(s.getName()+"("+cParams(s)+")");
       // Add constructor names to string buffer.
       // The user-defined cParams() method
       // returns parameters of the constructor.
    }
    ctr=1;
    while(ctr<constructors.length)
    // Repeat same process for all constructors
    {
       Constructor s=constructors[ctr];
       buffer.append(";"+s.getName()+"("+cParams(s)+")");
       // Add all constructor names to the string buffer separated with ";"

       ctr++;
    }
    lstConstructors.setListData(buffer.toString().split(";"));
    // Split constructor names and display them on JList
}
catch(ClassNotFoundException ex)
{
    JOptionPane.showMessageDialog(this, 
       "Invalid Class or Interface name. Check Classpath.",
       "Error",JOptionPane.ERROR_MESSAGE);
    // Show error if invalid class or interface name entered
}

获取方法参数类型的代码如下所示

public String params(Method m)
{
  // Get all parameter types
  Class[] parameters=m.getParameterTypes();
  StringBuffer buffer=new StringBuffer();
  if(parameters.length>0)
  {
     // Get first parameter type
     Class c=parameters[0];
     buffer.append(c.getName());
     // Add to buffer
  }
  int ctr=1;
  while(ctr<parameters.length)
  // Repeat for all parameters            
  {
     Class c=parameters[ctr];
     buffer.append(","+c.getName());
     ctr++;
  }
  return buffer.toString();
  // Return all parameter types
}

以下是如何获取构造函数的参数类型

public String cParams(Constructor s)
{
  // Get all parameter types
  Class[] parameters=s.getParameterTypes();
  StringBuffer buffer=new StringBuffer();
  if(parameters.length>0)
  {
     // Get first parameter type
     Class c=parameters[0];
     buffer.append(c.getName());
     // Add to buffer
  }
  int ctr=1;
  while(ctr<parameters.length)
  // Repeat for all parameters
  {
     Class c=parameters[ctr];
     buffer.append(","+c.getName());
     ctr++;
  }
  return buffer.toString();
  // Return all parameter types
}

关注点

该程序可以从命令行编译和运行如下

javac MyIntrospector.java
java MyIntrospector

我还创建了一个名为 MyIntrospector.jar 的可执行 jar 文件。 可以通过在 Windows 资源管理器中双击该文件来执行它。

© . All rights reserved.