Introduction
Introspection is an important feature of the Java language. Using introspection we can get the internal information of a class at run-time. This information includes methods, fields, constructors and so on. One use of introspection is in developing applications that use plug-ins. An application can determine the constructors, methods, and fields of the plug-in classes and use this information at run-time. Other uses of introspection are in creating Java Beans and developing Javadocs.
Background
The class to be introspected can be obtained using the forName()
method of the java.lang.Class
class. We can get an array of all the methods of a class using the getMethods()
method of java.lang.Class
. Similarly, we can use the getConstructors()
and getFields()
methods to get all the constructors and fields, respectively. The parameters of the methods and constructors can be obtained by using the getParameterTypes()
method of the Method
or Constructor
classes.
Using the Code
In the code, I have created a GUI consisting of a TextField
item to accept the name of the class to be introspected and three JList
items to display the methods, fields, and constructors of the class.
lblClassName=new JLabel("Enter a class name: ");
txtClassName=new JTextField(20);
lstMethods=new JList();
lstFields=new JList();
lstConstructors=new JList();
lstMethods.setToolTipText("Methods");
lstFields.setToolTipText("Fields");
lstConstructors.setToolTipText("Constructors");
getContentPane().add(panelInput,"North");
getContentPane().add(panelOutput,"Center");
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);
Here is the implementation of the actionPerformed
method:
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==txtClassName||e.getSource()==btnIntrospect)
{
if(txtClassName.getText().trim().length()==0)
{
JOptionPane.showMessageDialog(this,
"Please enter a Class or Interface name","Error",
JOptionPane.ERROR_MESSAGE);
return;
}
try
{
Class c=Class.forName(txtClassName.getText());
Here is how we get the methods information:
Method[] methods=c.getMethods();
StringBuffer buffer=new StringBuffer();
if(methods.length>0)
{
Method m=methods[0];
String t=m.getReturnType().toString();
if(t.startsWith("class"))
{
t=t.substring(6);
}
buffer.append(t+" "+m.getName()+"("+params(m)+")");
}
int ctr=1;
while(ctr<methods.length)
{
Method m=methods[ctr];
String t=m.getReturnType().toString();
if(t.startsWith("class"))
{
t=t.substring(6);
}
buffer.append(";"+t+" "+m.getName()+"("+params(m)+")");
ctr++;
}
lstMethods.setListData(buffer.toString().split(";"));
Getting the fields information is as follows:
Field[] fields=c.getFields();
buffer=new StringBuffer();
if(fields.length>0)
{
Field f=fields[0];
String t=f.getGenericType().toString();
if(t.startsWith("class"))
{
t=t.substring(6);
}
buffer.append(t+" "+f.getName());
}
ctr=1;
while(ctr<fields.length)
{
Field f=fields[ctr];
String t=f.getGenericType().toString();
if(t.startsWith("class"))
{
t=t.substring(6);
}
buffer.append(";"+t+" "+f.getName());
ctr++;
}
lstFields.setListData(buffer.toString().split(";"));
This is how we get the constructors information:
Constructor[] constructors=c.getConstructors();
buffer=new StringBuffer();
if(constructors.length>0)
{
Constructor s=constructors[0];
buffer.append(s.getName()+"("+cParams(s)+")");
}
ctr=1;
while(ctr<constructors.length)
{
Constructor s=constructors[ctr];
buffer.append(";"+s.getName()+"("+cParams(s)+")");
ctr++;
}
lstConstructors.setListData(buffer.toString().split(";"));
}
catch(ClassNotFoundException ex)
{
JOptionPane.showMessageDialog(this,
"Invalid Class or Interface name. Check Classpath.",
"Error",JOptionPane.ERROR_MESSAGE);
}
The code for getting the parameter types for methods is listed below:
public String params(Method m)
{
Class[] parameters=m.getParameterTypes();
StringBuffer buffer=new StringBuffer();
if(parameters.length>0)
{
Class c=parameters[0];
buffer.append(c.getName());
}
int ctr=1;
while(ctr<parameters.length)
{
Class c=parameters[ctr];
buffer.append(","+c.getName());
ctr++;
}
return buffer.toString();
}
Here is how we get the parameter types for the constructors:
public String cParams(Constructor s)
{
Class[] parameters=s.getParameterTypes();
StringBuffer buffer=new StringBuffer();
if(parameters.length>0)
{
Class c=parameters[0];
buffer.append(c.getName());
}
int ctr=1;
while(ctr<parameters.length)
{
Class c=parameters[ctr];
buffer.append(","+c.getName());
ctr++;
}
return buffer.toString();
}
Points of Interest
The program can be compiled and run from the command line as follows:
javac MyIntrospector.java
java MyIntrospector
I have also created an executable jar file called MyIntrospector.jar. This file can be executed by double clicking on it in Windows Explorer.