Java: a Survival Guide -- Exercises
The exercises presented here are companions to the presentation Java: a Survival Guide (PDF, PPT). During this session, we'll be refering to the Java API documentation.
We'll be working all our exercises in the
java/dev/basicjava directory, so to set-up, we change
into that directory.
on Linux/MacOS:
cd $NVOSS_HOME/java/dev/basicjava |
on Windows:
cd %NVOSS_HOME%\java\dev\basicjava |
|
Exercise 0: Compiling and Running a Simple Java Program
- If you ran ant previously, return our directory to
its pristine state by typing
ant distclean. -
Download and save to the current directory HelloWorld.java.
-
Compile the source code:
javac HelloWorld.java
You will now notice that you have a class called
Hello.classin the current directory. -
Run your compiled code:
java HelloWorld
Technically speaking, thejavacommand will:- Start the Java Virtual Machine (JVM)
- Load the class file into the JVM
- Find and execute the
main()method.
Exercise 1: Understanding Packages and the CLASSPATH
Warning: This exercise will generate errors on purpose.
-
In the same directory, compile our slightly more complex Hello-world program,
Hello.java:javac -g Hello.java
Here's a tip: When I compile code by hand (instead of using Ant), I always include the
-gflag. This enables debugging mechanisms; in particular, when an exception is thrown, the line number of the source code where the error occurred will be printed. Very helpful! -
Now run the application:
java Hello
Oops! Did you see this as your output?
Exception in thread "main" java.lang.NoClassDefFoundError: Hello (wrong name: nvoss/basicjava/Hello) at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:537) ...What went wrong? (See slide 18.)
-
Create a source directory tree for our source code and copy our code into it:
on Linux/MacOS: mkdir -p nvoss/basicjava cp Hello.java nvoss/basicjava cd nvoss/basicjava
on Windows: mkdir nvoss\basicjava copy Hello.java nvoss\basicjava cd nvoss\basicjava
-
Now recompile and execute:
javac -g Hello.java java nvoss.basicjava.Hello
Now what?
NoClassDefFoundErrorusually means something is wrong with our CLASSPATH, so let's have a look at it:on Linux/MacOS: echo $CLASSPATH
orecho $CLASSPATH | sed -e 's/:/\n/g'
on Windows: echo %CLASSPATH%
We could fix this problem this problem by adding the full path to our
basicjavadirectory to our classpath...on Linux/MacOS, csh: setenv CLASSPATH ${CLASSPATH}:$NVOSS_HOME/java/dev/basicjavaon Linux/MacOS, sh:CLASSPATH=${CLASSPATH}:$NVOSS_HOME/java/dev/basicjavaon Windows:set CLASSPATH=%CLASSPATH%;%NVOSS_HOME%\java\dev\basicjava
However, there is a simpler solution in our case. We see that "." (the current working directory) is one of the directories in the CLASSPATH. Thus, we need only change back into the
basicjavadirectory to execute the application.on Linux/MacOS: cd ../.. java nvoss.basicjava.Hello
on Windows: cd ..\.. java nvoss.basicjava.Hello
Aaahhh. That's more like it.
Exercise 2: Simple Creation and Manipulation of Objects
One this one, you get to fly solo.
Assignment: Edit
Hello.java to say hello to each word given on the command
line.
The resulting behavior should look like this:
> java nvoss.basicjava.Hello George Tony Junichiro Hello George! Hello Tony! Hello Junichiro!
Need a co-pilot? Have a look at Hello2.java in the
solutions directory.
Exercise 3: Extending a Class
Assignment: Extend the
Hello class to print a different salutation.
For example, we can create a class called FrenchHello
with the following behavior:
> java nvoss.basicjava.FrenchHello Allo le monde!
I'll get you started.
-
If you want to save on some typing, download FrenchHello.java and save it in our
nvoss/basicjavadirectory. -
Edit
FrenchHello.javato begin the definition of your new class. Start by declaring the class's package to benvoss.basicjava, and then add the class definition line so that it extendsHello. (This is already done in FrenchHello.java.)Our sample looks something like this:
package nvoss.basicjava; public class FrenchHello extends Hello { } -
Add constructors.
We probably want the same interfaces as our parent class,
Hello--that is, one constructor where the user can provide the addressee's name and one in which the user provides nothing and a default is used.Stubs for these constructors appear in our skeleton:
public FrenchHello(String toWho) { } public FrenchHello() { }Now lets fill them in. In the first constructor, we need to pass the user's input string. To do this, we simply call the "super" constructor with
super(toWho). We could do something similar for the second constructor by insertingsuper()(to callHello's "no-arg" constructor); however, it would be good to override theHello's default addressee ("world") with something more...french. We can do this by calling the first constructor inside the second by insertingthis("le monde"). -
Override the
getGreeting(String toWho)method.Cut-and-paste this method from
Hello.javaand modify its implementation. -
Override the
main()method to use our extended class.Given that static methods are inherited along with other methods, why do we need to override main() in this case?
-
Compile and run the new class.
Extra Credit: Use the
Hello class print the English translation immediately
after the modified greeting(s). Before you start doing a lot of
cut-and-pasting, is there a simple way to accomplish this?
Need some more help? You can peek at the
FrenchHello.java file in the solutions directory.
Exercise 4: Common errors and exceptions
In this exercise, we'll intentionally break Hello.java in
several ways to see what kinds of errors occur. After completing each
modification described below, compile and run the modified app, then
write down answers for the following questions:
- Was the problem detected at compile-time
(when you ran
javac) or at run-time (when you ranjava)? - Was an exception thrown? What the name of the exception?
- What line number did the error occur at?
Be sure to fix the resulting error before going onto the next step.
And don't forget to use the -g option with
javac.
-
Comment-out the line that creates our
Helloobject,greeter, inmain():// Hello greeter = new Hello(); -
Now explicitly set
greeterto null:Hello greeter = null; // = new Hello();Note: sometimes variables can get set to null in non-obvious ways at run-time; this step illustrates what can happen in such a case.
-
Remove the initialization of the private member
who:private String who;How and why was the outcome of the error different from step 2? -
Make
main()over-run the bounds of the argument array when it is passed a list of names. This step assumes that you have completed Exercise 2.for(i=0; i <= args.length; i++) {^ -
Comment out the
importstatement with the wildcard.// import java.io.*;
-
Comment out the
throwsstatement modifying thesayHello(Writer)method.public void sayHello(Writer out) // throws IOException {
Exercise 5: Handling Exceptions
Assignment: Create a new application
that will write Hello's greeting to a file.
Tips:
-
You don't need to create a sub-class of
Helloto accomplish this one as we did in Exercise 3. You can useHello's existing interface from amain()method. -
The
FileWriterclass from thejava.iopackage is used to write to files. Consult the Java Package API documentation to get details. -
For extra credit, you might want to put in some code to check file existence and/or permission to write. The
Fileclass, also from thejava.iopackage, handles this. -
Remember, this exercise is supposed to be about exceptions, so if you are not handling them, then you're probably doing something wrong.
Stumped? You can peek at HelloToFile.java in the
solutions directory, or you can look
here for a full explanation.
