Creating object instances out of a class name
Basic means
Frequently, you have to create an object instance out of just a class name, especially in J2EE
applications, where you use interfaces, against you program the application, and want to configure
some implementation classes of these interfaces in an XML file. At application startup, you
read this configuration and create the specified objects.
The basic mean for this behaviour is the class Class which helps us with the
creation of object instances.
Example
The following example assumes that there is an interface IPlugin which describes a
plugin interface with a method execute(String):
public interface IPlugin {
public String execute(String pstrArgs);
}
The implementation of this interface
can be given as (fully specified) class name at the command line prompt, e.g.
java Test de.kksoftware.krims.MyPlugin "Hi Ingo"
The program try to find the specified class, get an appropriate class object and creates an object
instance (the example code can be downloaded here):
public class ClassTest {
public static void main(String args[]){
// get parameter
if (args.length != 2){
System.out.println("usage: java Test ");
System.exit(0);
}
String strClassName = args[0];
String arg = args[1];
// first, get the class template for the requested object
Class oclsPlugin = null;
try {
oclsPlugin = Class.forName(strClassName);
} catch (ClassNotFoundException e){
System.out.println("class not found: " + strClassName);
System.exit(1);
}
// then create an object instance out of the class template and try
// to cast it to the desired interface
IPlugin oPlugin = null;
try {
Object o = oclsPlugin.newInstance();
if (o instanceof IPlugin){
oPlugin = (IPlugin)o;
} else {
System.out.println(strClassName + " does not support IPLugin interface");
System.exit(1);
}
} catch (InstantiationException e){
System.out.println("class not instantiated: " + strClassName);
System.exit(1);
} catch (IllegalAccessException e){
System.out.println("class not accessible: "+ strClassName);
System.exit(1);
}
// execute a test method on the created object
String strResult = oPlugin.execute(arg);
System.out.println("Ergebnis: " + strResult);
}
}
|
Note that we first have to get a Class object. We can achive this goal by
two means:
- The first one is shown in the example, we just have the class name and use the method
forName(String) of the Class object to get the class template itself;
- we can get a class itself by using a construction like
Class oclsPlugin = de.kksoftware.krims.MyPlugin.class;
// or from an object instance
MyPlugin oPlugin = new MyPlugin();
Class oclsPlugin = oPlugin.getClass();
This way is preferrable if you do not want to configure the class, but hard-code it. This is
very appropriate if you have, e.g. a method call whose return type you want to specifiy,
as in
List getAllX(Class pclsReturnType){
// create a List of elements which have the specified class
}
In this way, you can easily get a List with elements of a specified class.
Class information
If you have a Class object, you can examine it for debugging purposes by simply
printing it to an output stream. For the following code fragmet, you get an output like this:
Myplugin p = new MyPlugin();
System.out.println("p="+p);
System.out.println("p="+p.getClass().getName());
// yields:
// p=MyPlugin@78c37
// p=MyPlugin
The output consists of the class name, followed by the address of the object. Most of the time,
the class name is the interesting part of the output, especially if you have a very dynamic system
where you want to know which classes are really used. In this case, you can get the class of the
object by getClass() and call the getName() method of it. Then you
get only the class name. An advantage of this approach is the fact that some classes may have
overwritten the toString() method and prints out a senseful value instead of
the class name, as the String class do. The getName() method always
returns the class name, regardless of a senseful textual representation.
In some cases, the output is more complex, as in the example below:
String sa[] = new String[3];
System.out.println("sa="+sa.getClass().getName());
int ia[] = new int[3];
System.out.println("ia="+ia.getClass().getName());
// yields:
// sa=[Ljava.lang.String
// ia=[I
In this strange output, each [ denotes an array level, followed by the class name, as
expected. The I codes the class of an primitive type of int due to the
following general table:
| (Primitive) type |
Code |
byte |
B |
char |
C |
double |
D |
float |
F |
int |
I |
long |
J |
| class or interface |
L<classname>; |
short |
S |
boolean |
Z |
void |
V |
Note that for each array level, you get an additional [ sign.
Calling methods on a Class object
With an object of class Class, you can do very exciting things such as calling
a method if you only have the textual (String) representation of the method name. You do this
in the following manner:
try {
// get an object and its class
MyPlugin p = new MyPlugin();
Class oclsPlugin = MyPlugin.class;
// prepare the call
Class[] oclsSignature = new Class[]{ String.class };
java.lang.reflect.Method oM = oclsPlugin.getMethod("execute", oclsSignature);
// execute the method
System.out.println("Result is " + oM.invoke(p, new Object[]{ "Ingo" }));
} catch (java.lang.reflect.InvocationTargetException te){
System.out.println("invocation target exception");
} catch (NoSuchMethodException me){
System.out.println("No such method");
} catch (IllegalAccessException ie){
System.out.println("Illegal access");
}
The getMethod(String, Class[]) retrieves a Method object on which you
can invoke the desired method which is given as the String parameter. The second parameter
is an array of Class objects which specifiy the parameter
types (the signature) of the desired method, if necessary. To execute the method, you call the
invoke method on the Method(Object, Object[]) object, supplying the
object instance which is to be used for the call, and an array of parameters. Here, we have one
single parameter of type String.
back to toolbox page
|