Letters to the Editor

New Media Programming columnist Bill Day does his honorable best to answer all his mail -- praise, suggestions and grumbles alike. Plus: Bill Venners fields a slew of tough Design Techniques-related questions, Mark Johnson sets the record straight on serializing class objects, and more

1 2 3 Page 3
Page 3 of 3
package com.artima.somelib;
                                       public class MyLib {
                                       public static class SplitNameReturnVal {
                                       private String title;
                                       private String first;
                                       private String middle;
                                       private String last;
                                       private SplitNameReturnVal(String title, String first, String
                                       middle,
                                       String last) {
                                       this.title = title;
                                       this.first = first;
                                       this.middle = middle;
                                       this.last = last;
                                       }
                                       public String getTitle() {
                                       return title;
                                       }
                                       public String getFirst() {
                                       return first;
                                       }
                                       public String getMiddle() {
                                       return middle;
                                       }
                                       public String getLast() {
                                       return last;
                                       }
                                       }
                                       public static SplitNameReturnVal splitName(String name) {
                                       // Do processing to actually split the name into its
                                       // component parts. For now, just return Jane Q. Public.
                                       return new SplitNameReturnVal("Ms.", "Jane", "Q.", "Public");
                                       }
                                       }
                                       -----------------------
                                       import com.artima.somelib.MyLib;
                                       class Test {
                                       public static void main(String[] args) {
                                       MyLib.SplitNameReturnVal sn =
                                       MyLib.splitName("Mr. F. Scott Fitzgerald");
                                       System.out.println(sn.getLast() + sn.getMiddle() + sn.getFirst()
                                       + sn.getTitle());
                                       }
                                       }
                                      

As you can see, I'm in the create-a wrapper-object-and-return-it camp, which you mentioned is your preferred solution. However, I made it an immutable static inner class with a private constructor. This means only

MyLib

and its inner classes can instantiate a new wrapper object, and once it's created it can't be changed. The sole purpose of the wrapper object's short life is to return data from

splitName()

to its caller. This design does require that you write a lot of classes (in your case 50 of them) just to return data, but at least they're inner classes, so they sit in the same source file as the method whose data they're returning. This design also means you're creating a lot of short-lived objects at runtime, which may cause you to worry about performance. For my thoughts on the performance subject, see my article "

The Hotspot virtual machine

at developer.com. As I said at the start, there is no right or wrong answer to this design problem. The above code just shows how I would approach the particular problem of

splitName()

. Bill Venners

Under the Hood: "Security and the class verifier" by Bill Venners

Read

Illegal cast

Bill,

I noticed your article about class loaders on the JavaWorld site. I've tried to implement my own class loader for an applet but I've run into a problem: I'm getting a ClassCastException during the instantiation of the object loaded from my classloader. For example:

 
                                       Class c = myloader.loadClass("com.foo.MyClass");
                                       // This gets the ClassCastException
                                       com.foo.MyClass myclass = (com.foo.MyClass)c.newInstance();
                                      

I've tried to load MyClass with the primordial classloader and I still get the ClassCastException problem. Any ideas or debug tips?

Michael Maresca

Michael, The exception you are getting just means that you are attempting an illegal cast. The type of reference you are trying to cast from is not castable to the reference you are trying to cast to. The above code doesn't tell me exactly what the problem is. One thing that comes to mind is that if your class loader is loading MyClass itself (instead of calling findSystemClass() and getting it from the system loader) the cast won't work. Even though your class loader loaded the same class file as the system loader, your class loader called defineClass() to import the type. This results in two copies of the class data for the MyClass type, one for each name space. In other words, the system class loader name space has one copy of the class data for MyClass. The name space for your class loader uses a different copy of the class data for MyClass. When you try to cast an instance of MyClass (defined in your class loader's name space) to a reference of type MyClass (defined in the system class loader's name space), you'll get a ClassCastException. Even though the two copies of the MyClass class data are identical, the VM doesn't bother to figure that out. They have to be the same class data. To solve this problem, call findSystemClass() in your class loader before trying to import the type in your custom way. Bill Venners

JavaBeans: The beans-serialization series by Mark Johnson

ReadReadRead

Class objects: completely serializable

Is it true that you cannot serialize class objects, only instances of existing (that is, already loaded) classes? I've been told so, but I couldn't find this restriction spelled out in the specification.

Olivier Lefevre

Olivier, According to the Java 1.1.4 documentation,

class

objects are serializable. And everything seems to work fine. Also, it doesn't matter if the class is already loaded or not: If it's not loaded,

java.Class.forName()

tries to load and link it. See the example below:

// Sample class "SerClass"
                                       import java.io.*;
                                       public class SerClass {
                                           private static void Usage()
                                           {
                                               System.out.println("Usage:\n\tSerClass w file classname\n\tSerClass
                                       r file");
                                               System.exit(1);
                                           }
                                           public static void main(String[] args)
                                           {
                                               String cmd = args[0];
                                               try {
                                                   if (cmd.compareTo("w") == 0) {
                                                       if (args.length != 3)  { Usage(); }
                                                       String classname = args[2];
                                                       Class   theClass = Class.forName(classname);
                                                       FileOutputStream f = new FileOutputStream(args[1]);
                                                       ObjectOutputStream s = new ObjectOutputStream(f);
                                                       System.out.println("Writing class " + classname);
                                                       s.writeObject(theClass);
                                                       s.flush();
                                                   }
                                                   else if (cmd.compareTo("r") == 0) {
                                                       if (args.length != 2) { Usage(); }
                                                       FileInputStream f = new FileInputStream(args[1]);
                                                       ObjectInputStream s = new ObjectInputStream(f);
                                                       Class theClass = (Class) s.readObject();
                                                       System.out.println("Read a class object for class " +
                                                                          theClass.getName());
                                                   }
                                                   else {
                                                       System.err.println("Unknown command " + cmd);
                                                       Usage();
                                                   }
                                               }
                                               catch (IOException ex) {
                                                   System.out.println("IO Exception:");
                                                   System.out.println(ex.getMessage());
                                                   ex.printStackTrace();
                                               }
                                               catch (ClassNotFoundException ex) {
                                                   System.out.println("ClassNotFound Exception:");
                                                   System.out.println(ex.getMessage());
                                                   ex.printStackTrace();
                                               }
                                           }
                                       };
                                       // END OF CLASS FILE
                                      

OUTPUT:

======= C:\>java SerClass w x java.lang.Integer

Writing class java.lang.Integer C:\>java SerClass r x

Read a class object for class java.lang.Integer Hope this helps. Mark Johnson

Letters to the editor

Sun: Quit the courtroom and cooperate

To the editor:

When Java first came out, I think I was the first one in the Middle East to buy a how-to Java book. I thought -- and still think -- that it is the greatest idea in the computer world. But, I am continually surprised by Sun's attempts to kill Windows through the court system instead of through innovation. I always thought that the best thing for Sun to do, if it really wanted to spread the Java gospel, was to cooperate with Microsoft. The latter is a company with a huge experience in developing superior applications that meet customer needs. Its secret, I think, is that it listen to its customers. Sun, is slow in listening to its customers. In addition, Sun has no experience in producing programs for the wide market Java is targeting, while Microsoft does.

I would like to say that Microsoft's existence and competitiveness have always been great factors enhancing competition in the industry. Other companies in the sector have always worked very hard to keep up with MS and overcome it. I think this applies to Sun. It seems to me that Mr. McNealy's enthusiasm is spurred by his desire to replace Windows. Thus, I think that Sun's Java wouldn't have progressed as fast as it has without Microsoft in the game.

Java is still far from perfect. I think Java would advance much faster if we quit the courtroom and cooperated. That is, if we're really interested the consumer's benefit, as Mr. McNealy likes to say.

Jabra Ghneim

Amman, Jordan

Reprints

To the editor:

What is JavaWorld's official position on readers printing JavaWorld articles and sharing them with colleagues?

Carlos Valcarcel

Carlos, For distribution to a few friends and colleagues, feel free. For wider distribution -- or for any distribution designed to help promote your commercial endeavors, products, or services -- please consult with our reprints group: Reprint Management Services

717-560-2001

Charles Calta

sales@rmsreprints.com

Jeff Martin, reprint operations specialist, 717-560-2001 ext. 31

http://www.rmsreprints.com Michael O'Connell

Editor-in-Chief

michael.oconnell@javaworld.com

Related:
1 2 3 Page 3
Page 3 of 3