|
| |
Using the Bare Java Software Development Kit
Caveats
The first thing I should say about using the bare Java SDK is:
Don't do it, unless you
absolutely know you want to, and are comfortable with a
UNIX-style command line, and other UNIX concepts. Believe me, it's not what I would
call a user-friendly environment.
I strongly recommend a Java IDE for the following reasons:
- Java IDEs hide a lot of the user-hostile stuff. In particular, the
class path is usually integrated in a more user-friendly manner in an
IDE. The class path is, in my experience, the biggest problem students
have with Java.
- Java IDEs provide a more pleasant, integrated (that's the I in IDE)
experience; there's a simple to use editor, and lots of ease-of-use
features.
- Good Java IDEs provide a visual debugger, which is light years ahead of
the debugger that comes with the JSDK when it comes to the user interface. This can be invaluable
when you're stuck trying to figure out why your latest and greatest class
doesn't work correctly.
However, if you really, really, insist on using the bare Java SDK, here's
some help getting started:
Essential Links
One of the first things you should do when you start with Java is go to the
Sun Microsystems Java web site. Point your browser at http://java.sun.com/
I recommend that you register. It's free, and the benefits are
enormous! This is true whether you plan to use the bare Java SDK or
not.
This site is a rich source of lots of Java-related information. Two
places, in particular, are particularly useful:
Again, all these links are very valuable no matter how you use your Java
development environment.
The Basic Java Tools
There are basically two tools you'll be using in this course:
javac -- the Java compiler, which translates
Java source files into Java class files.
java -- the Java Application Launcher, which
implements a Java Virtual Machine, and executes Java programs.
There are other tools, but you tend to use them a lot less.
Starting Out
Imagine you have written a Java class Foo, which looks like this:
public class Foo
{
public static void main(String[] args)
{
System.out.println("Hello, Universe!");
}
}
Remember that this source must be entered into a class with a name Foo.java
(the file name must be exactly the same as the class name)
You compile this source file with the following command (assuming your
current working directory is the same one as that of the .java
file) :
javac Foo.java
That should work. If you receive no errors, you should find a Foo.class
file in your current working directory.
So, now, you try to run the program using the following command:
java Foo
Note that you must not say java Foo.class.
If you do, you will get:
Exception in thread "main" java.lang.NoClassDefFoundError: Foo/class
Specifying:
java Foo
will cause the class to run, and the output will be:
Hello, Universe!
Placing a Class in a Package
So far, so good. What if we create a new class Foo2,
that looks like this:
package bar;
public class Foo2
{
public static void main(String[] args)
{
System.out.println("Hello, Universe!");
}
}
The only differences are that the class has a (slightly) different name, and
that it now exists inside a named package, bar.
So, let's compile it:
javac Foo2.java
That works. Now, let's try to run it:
java Foo2
Here's what I received when I tried it:
Exception in thread "main" java.lang.NoClassDefFoundError:
Foo2 (wrong name: bar/Foo2)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:537)
at java.security.SecureClassLoader.defineClass
(SecureClassLoader.java:123)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
The notorious NoClassDefFoundError !
What's wrong?
You need to fully qualify the class name with its package name when you run
it using the Java Application Launcher.
java bar.Foo2
However, when I tried doing this, I received the following:
Exception in thread "main" java.lang.NoClassDefFoundError: bar/Foo2
So, this isn't the right way to handle the case of classes within explicit
packages.
Using Package Names
So how are you supposed to handle things, when you use package names with
classes? Here's our Foo2 class again:
package bar;
public class Foo2
{
public static void main(String[] args)
{
System.out.println("Hello, Universe!");
}
}
First, we use the following command to compile this class:
javac -d . Foo2.java
The -d option specifies the 'destination'; the
directory where the Java compiler will place the class files it produces.
In the case where the class is within a specified package, say bar,
the -d option specifies a base directory;
the resulting class file will be placed in a subdirectory of the base directory
which has the same name as the package name. The "-d ." means
that the destination is the current working directory (the dot means
"current directory").
So, when we issue the above command, the javac
compiler creates a Foo2.class file in a
subdirectory bar, below the current working directory. The compiler
creates the necessary subdirectory/ies in order to create the necessary class
file(s).
Now, we can try running the resulting class:
java bar.Foo2
which produces:
Hello, Universe!
This works because:
- We created the class file in the appropriate subdirectory, and
- We happen to use a default class path that works in this case.
If we were to run from a different working directory, things wouldn't work so
smoothly.
Doing Things Right
Here's what you should be doing:
- For each Assignment (or independent project), create a directory
somewhere. For assignment 1, for example, call it, say,
Ass1.
This directory will be the base directory for all files related to this
project/assignment.
- Below
Ass1, create two subdirectories, src
and classes.
- Specify a class path that includes this classes subdirectory, and set it into the CLASSPATH environment
variable. The class path should be something like:
set CLASSPATH="C:/Ass1/classes"
- When you wish to create a new Java class (say
Foo2)
within a package, say, bar, create its source
file in a subdirectory of src, called bar,
creating the bar subdirectory if necessary.
- When you compile a class, use the following command:
javac -sourcepath "C:/Ass1/src" -d "C:/Ass1/classes" ClassName.java
where 'ClassName' represents the name of the class. Note
that we're specifying that the destination of Java compilations is the Ass1/classes
subdirectory. (Here, I'm using a specific place where these files will
reside on a Windows system; if your location is different, change the C:/Ass1/src
to a more appropriate value.) This will result in the .class
files being generated in the proper subdirectory below the classes
subdirectory.
In addition, I'm specifying a source path (like a class path, except for
source files) that points to the base src
subdirectory.
Note that the above command relies on the CLASSPATH environment variable
being set up.
- When you run a class, use the following command:
java packageName.ClassName
which specifies that the class to be run lives in the specified package.
Note that the above command relies on the CLASSPATH environment variable
being set up.
Following these rules should allow you to develop a number of Java
classes within one or more packages, and keep your sanity!
Note that every IDE enforces somewhat similar rules. It's just that
you don't have to do all the hard work when you use an IDE; they do it
for you!
|