Friday, October 26, 2007

JavaSpecialists Notes - II

Issue 18: Class names don't identify a class

We can also let these two "A" classes have a common superclass. For example, 
say we have a superclass called Parent.java located in the root directory:

//: Parent.java
public class Parent {
public String toString() {
return "Thanks for caring... but what do you want??? ";
}
}

And our A.java classes are now written as:

//: a1/A.java
public class A extends Parent {
public String toString() {
return super.toString() + "This is the first class";
}
}
//: a2/A.java
public class A extends Parent {
public String toString() {
return super.toString() + "This is the second class";
}
}

We then need to have a common parent ClassLoader which we use to load the
Parent.class file. We have to specify the location to start looking for
Parent.class, and the locations are searched in a hierarchical fasion. Note that the
compile-time Parent class is loaded with a different ClassLoader to the one loaded
with the URLClassLoader called "parent" so they refer to a different class
altogether, which means we cannot type-cast an instance of "A" to a Parent. Also, if
we load the class "Parent" without using the classloader, we will see that it is not
equal to the superclass of "c1".

//: Loader.java
import java.net.*;
public class Loader {
public static void main(String[] args) throws Exception {
ClassLoader parent = new URLClassLoader(
new URL[] {new URL("file:./")}, null);
ClassLoader a1 = new URLClassLoader(
new URL[] {new URL("file:a1/")}, parent);
ClassLoader a2 = new URLClassLoader(
new URL[] {new URL("file:a2/")}, parent);
Class c1 = a1.loadClass("A");
Class c2 = a2.loadClass("A");
System.out.println(c1.newInstance());
System.out.println(c2.newInstance());
System.out.println(
c1.getSuperclass().equals(c2.getSuperclass()));
System.out.println(
Class.forName("Parent").equals(c1.getSuperclass()));
try {
Parent p = (Parent)c1.newInstance();
} catch(ClassCastException ex) {
ex.printStackTrace();
}
System.out.println("We expected to get ClassCastException");
}
}

Thanks for caring... but what do you want??? This is the first class
Thanks for caring... but what do you want??? This is the second class
true
false
java.lang.ClassCastException: A
at Loader.main(Loader.java:18)
We expected to get ClassCastException

Note that the super classes of both "A" classes are equal.

Where is this all this useful? It is very useful when you have an application server
into which you want to deploy business objects written by different people. It is
entirely feasible that you have two developers with different versions of classes
deploying their applications onto the same server. You don't necessarily want to
start a new VM for each deployment, and so with ClassLoaders it is possible to have
lots of classes with the same name running in the same memory space but not
conflicting with one another. They would also share the common JDK classes with one
another, so we would not have to have a java.util.ArrayList class loaded for each of
the ClassLoaders.

No comments: