Four for the ages

Answers on threads, Class.forName(), multiple values, and shallow copying

This Q&A is a bit different in that I'm going to tackle four quick questions in one swoop. We'll look at green versus native threads, Class.forName(), returning multiple values from a method, and shallow copying. So, let's get to it.

Green and native threads -- what's the difference?

Question: What is the difference between green threads and native threads?

Answer: Green threads, the threads provided by the JVM, run at the user level, meaning that the JVM creates and schedules the threads itself. Therefore, the operating system kernel doesn't create or schedule them. Instead, the underlying OS sees the JVM only as one thread.

Green threads prove inefficient for a number of reasons. Foremost, green threads cannot take advantage of a multiprocessor system. Since the JVM simply runs from within one thread, the threads that the JVM creates are not threads at the OS level. Instead, the JVM splits its timeslice among the various threads that it spawns internally. Thus, the JVM threads are bound to run within that single JVM thread that runs inside a single processor.

In contrast, native threads are created and scheduled by the underlying operating system. Rather than create and schedule threads itself, the JVM creates the threads by calling OS-level APIs. As a result, native threads can benefit from multiple processors. Performance can improve because an IO-blocked thread will no longer block the entire JVM. The block will only block the thread waiting for the IO resource.

There are times when you might want to run green threads. First, native threads are not always available. Second, if your code is not thread-safe, you may experience errors when running native threads.

What does Class.forName(); do?

Question: What exactly does the Class.forName(); statement do? Why is this construct encountered only with JDBC? (I have not seen any code that uses Class.forName() in other contexts.) Answer: Every object has a corresponding class object. This class object instance is shared among all instances of that class type.

Class.forName() loads and returns the class object for the given class name. So, for example, if you write:

Class object = Class.forName("java.io.FileNotFoundException");

the JVM will load and return the class object for FileNotFoundException. Class objects play an important role in reflection. For example, you may call:

try
{
Class object = Class.forName("java.io.FileNotFoundException");
Object ex = object.newInstance();
}
catch (ClassNotFoundException ex) {}
catch (InstantiationException ex) {}
catch (IllegalAccessException ex) {}

In the example above, newInstance() goes out and instantiates an object for class if it has a no arguments constructor. You can also use the class object to obtain field, method, and interface information.

The example given above is a bit contrived. However, let's say you define an interface that provides a proxy to some backend server. Your program knows how to manipulate the interface; it does not, however, know which interface implementation to instantiate at compile time. Instead, you provide that class name as a command line argument. Your program can use reflection to go out and instantiate that object.

In the case of JDBC, the Class.forName() loads the JDBC driver into the JVM.

Return multiple values from a method

Question: How can I return more than one value from a method in Java?

Answer: Two easy ways exist to return multiple values from a function:

  1. Precondition: Method 1 works only if the return values are all of the same type -- all values must be integers or booleans, and so on.

    If your return values meet the precondition, simply return an array of values.

    If your values are of different types, you could cast them all down to object and return them as an array of object. However, this proves dangerous work and requires your method's caller to possess too much knowledge of how the array is filled in.

  2. No precondition: With method 2, simply create a high-level wrapper object. For example, if you would like to return an int, a float, and a boolean, create the following wrapper:

    public class SimpleWrapper
    {
        public SimpleWrapper(int I, float f, boolean b)
        {
            _anInt = I;
            _aFloat = f;
            _aBoolean = b;
        }
        public int getInt() { return _anInt; }
        public float getFloat() { return _aFloat; }
        public boolean getBoolean() { return _aBoolean; }
        private int _anInt;
        private float _aFloat;
        private boolean _aBoolean;
    }
    

    Of course, the class and method names should make more sense in your context.

Shallow vs. deep copy

Question: I have questions about shallow copy and deep copy. Consider the following code:

Vector v = new Vector();
Vector v2 = v;

Is this the only way to make a shallow copy?

Answer: Actually, you have not done a shallow copy at all. Rather, by creating v and v2, you have created a second reference to the same object. A shallow copy will make a complete copy of the object and any primitive attribute. It will not, however, make copies of any high-level object attributes. Instead, it points those attributes at the reference in the original object.

For a good introduction to how Java treats references, read: "Does Java pass by reference or pass by value?" (JavaWorld, May 26, 2000).

Tony Sintes is a principal consultant at BroadVision. A Sun-certified Java 1.1 programmer and Java 2 developer, he has worked with Java since 1997.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more