Sponsored Link •
|
Advertisement
|
forName()
As an example of a Java application that performs dynamic extension with
forName()
, consider the EasyGreet
class:
// On CD-ROM in file linking/ex7/EasyGreet.java import com.artima.greeter.*; public class EasyGreet { // Arguments to this application: // args[0], args[1], ... - class names of greeters to load // and invoke the greet() method on. // // All greeters must implement the com.artima.greeter.Greeter // interface. // static public void main(String[] args) { if (args.length == 0) { System.out.println( "Enter greeter class names as args."); return; } for (int i = 0; i < args.length; ++i) { try { // Load the greeter specified on the command line Class c = Class.forName(args[i]); // Instantiate it into a greeter object Object o = c.newInstance(); // Cast the Object ref to the Greeter interface type // so greet() can be invoked on it Greeter greeter = (Greeter) o; // Greet the world in this greeter's special way greeter.greet(); } catch (Exception e) { e.printStackTrace(); } } } }
The EasyGreet
application is very similar to the Greet
application from the previous example. Like Greet
, EasyGreet
will attempt to dynamically load and execute greeters mentioned in command line arguments. But unlike
Greet
, EasyGreet
doesn't take as its first command line
argument a path name of the directory in which the class files for the greeters are stored. All of
EasyGreet
's command line arguments are greeter class names. Another difference is
that EasyGreeter
, because it is going to use forName()
to
load greeters dynamically, doesn't instantiate a GreeterClassLoader
. Then, where
Greet
invoked loadClass()
on its
GreeterClassLoader
instance, EasyGreet
invokes
forName()
, a static method of class Class
.
EasyGreet
's forName()
invocation looks very similar to
Greet
's loadClass()
invocation. Like
loadClass()
, forName()
accepts the fully qualified name of
the requested type in a String
parameter. If successful in loading the type (or if the
type had been loaded previously), forName()
, like
loadClass()
, returns the Class
instance that represents the
type. If unsuccessful, forName()
, like loadClass()
, throws
ClassNotFoundException
. The big difference between the two approaches is that
whereas loadClass()
attempts to ensure the requested type is loaded into the user-
defined class loader's namespace, forName()
attempts to ensure the requested type is
loaded into the current namespace -- the namespace of the defining class loader for the type whose method
includes the forName()
invocation.
Because forName()
is invoked from the main()
method of
class EasyGreet
, the class loader that forName()
asks to load
the requested type is EasyGreet
's defining class loader. When run from Sun's Java 2
SDK version 1.2, the class loader that loads EasyGreet
is the system class loader,
which looks for classes on the class path. To use the class path environment variable, you can execute the
EasyGreet
application in the linking/ex7
directory of the
CD-ROM with a command like this:
java EasyGreet Hello
If you don't specify a class path either explicitly on the command line or in an environment variable, the
system loader will look in the current directory for requested types. Because the current directory (the
linking/ex7
directory from the CD-ROM) doesn't contain
Hello.class
, the system class loader is unable to locate
Hello.class
. The forName()
method, and in turn
EasyGreet
's main()
method, completes abruptly with a
ClassNotFoundException
:
java.lang.ClassNotFoundException: Hello at java.net.URLClassLoader$1.run(URLClassLoader.java: 202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java: 191) at java.lang.ClassLoader.loadClass(ClassLoader.java: 290) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java: 275) at java.lang.ClassLoader.loadClass(ClassLoader.java: 247) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java: 124) at EasyGreet.main(EasyGreet.java, Compiled Code)
To enable EasyGreet
to find Hello.class
merely
requires that the greeters
directory be included in a class path specified on the
command line with the "-cp
" option, as in:
java -cp .;greeters; EasyGreet Hello
When started with this command, the EasyGreet
program prints:
Hello, world!
Like the Greet
method, EasyGreet
will accept multiple
greeter names on the command line:
java -cp .;greeters; EasyGreet Hello Greetings Salutations HowDoYouDoWhen invoked with this command, the
EasyGreet
application will load each of the
four greeters listed and invoke their greet()
methods, yielding this output:
Hello, world! Greetings, planet! Salutations, orb! How do you do, globe!
The important difference that arises from Greet
's use of
loadClass()
on GreeterClassLoader
and
EasyGreet
's use of forName()
is the namespaces into which
the greeter classes get loaded. In Greet
, the greeter classes get loaded into the
GreeterClassLoader
's namespace. In EasyGreet
, the
greeter classes get loaded into the system class loader's namespace.
Sponsored Links
|