In this lab you will learn to how use generic classes to write applications that deal with the issues of data type checking in a new way. In your next lab you will build on this knowledge, and learn how to work with a useful set of generic Java library classes known collectively as the Java Collections Framework.
Stack.java | StackTest0.java | StackTest1.java | StackTest2.java |
Now attempt to compile the single file StackTest0.java, without building the whole Lab13 project just yet. To do this, select the Projects view and right-click on the filename StackTest0.java. Then select the Compile File option in the popup menu.
The NetBeans output window should immediately display some red-line messages, as shown in the image below:
In slightly edited form (omitting full pathnames), the messages of concern read as follows:
Note: StackTest0.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
The compiler is trying to warn you here that your application
is not making totally correct use of the class Stack. That is
because the version of Stack.java
used in this lab is defined as a generic
class, and our StackTest0 application is ignoring that fact.
To see more details about this, right-click on the project name Lab13 and raise its Properties dialog (just the way you start out to add JAR files to your project classpath). But this time, instead of clicking the category Libraries in the left-hand subpanel, select the Build/Compiling option. This will raise a subdialog that appears as shown below:
Look for the blank textbox labeled Additional Compiler Options. Enter the option -Xlint:unchecked into this box, and then click OK. If you now attempt to compile StackTest0.java again, the output window should look even worse than before:
But if you look more closely, you should quickly see that these messages are all just warnings, not outright compiler errors. The main difference between the two is that warnings do not prevent the compiler from generating at least some sort of bytecode (.class files). In fact, if you try now to Run the file StackTest0 it should work just as you might expect it to:
Stack stack = new Stack();
and change it to read as follows:
Stack<Object> stack = new Stack<Object>();
As you can probably guess, this change tells the compiler explicitly
that stack will accept Object values (which in effect
includes all other types of objects, such as String,
Color, or whatever). With the original version the compiler
actually ended up making this same assumption, but only after issuing a
warning about the use of raw types (generic classes with no type
parameters in angle brackets).
Try making this one change and recompiling StackTest0. You should see the warnings go away. And of course when you run StackTest0 it should work just as it did before.
When you reach this point, show your new version of StackTest0 to your lab instructor.
Use the Compile File menu option to compile StackTest1. As you should expect, the compiler will again issue warnings about the use of raw types. As a first attempt to remove these warnings, try changing the Stack declaration to
Stack<Object> stack = new Stack<Object>();
and recompile. You should no longer see the warnings.
That is progress, but you can do better: go back and change the declaration to read
Stack<Integer> stack = new Stack<Integer>();
and try again. You should still see no warnings. But now
go in again and change the line that reads
sum += (Integer) stack.pop();
to
sum += stack.pop();
In other words, remove the cast operator. The cast to
the Integer type is in fact unnecessary if the
compiler knows that the Stack can store only
Integer values. In a larger program, the ability to
remove lots of cast operators can be a major improvement.
But the restriction to the Integer type has another
advantage: now the compiler can detect possible errors that
otherwise would have been found only later at runtime, usually
in the form of a ClassCastException.
As a simple illustration of this last point, open StackTest2.java in the NetBeans editor. This is a tiny application that creates two Stack instances, one for String values and one for Integer values. Compile and run this program as is, just to be sure that you get no warnings about raw types and that its output is what you would expect. Then try adding lines like
strs.push(789);
or
ints.push("789");
to the sequences of push() statements. In either case the
compiler should immediately report an error, and in fact pinpoint the
line number where the error actually occurred. With runtime
ClassCastException
errors, the reported line may be far from the point where the real
error was made. It is for both of these reasons that generic classes
were introduced into the Java language as of version 1.5.
public class Stack<E>
The symbol E is just a placeholder, which serves very much
the same purpose as a parameter name in a method definition.
Later in the code you will see occurrences of E where you
might have expected, say, Object to appear. What happens
is that when an application makes a declaration like
Stack<Integer> stack = new Stack<Integer>();
the generic definition is used to make a new Stack object,
in which all references to E are replaced by Integer.
Of course that is just the first approximation to the truth, and there are lots of details that are glossed over here. But just knowing this much should enable you to convert a simple, ordinary class definition into its generic equivalent. Now your textbook actually defines several generic demo classes in Chapter 21, including its own version of a GenericStack (Listing 21.1, p. 688). So by following any of these examples you could easily implement a generic version of a Queue as your final exercise in this lab. But to make things at least slightly more interesting, you get to deal with the List class that you encountered earlier in your labs. To start out, download the following two additional files and import them into your Lab13/src/lab13 project folder:
List.java | ListTest.java |
Your task is simply to convert the class definition for List into a generic version. Of course you should use Stack.java as a guide, and you may also get help from looking at the textbook demos.
When you get the List conversion done, you should be able to
compile and run the test application
As usual, be sure to show your final results to your lab instructor
before you logout.
When your project is complete and working correctly, demonstrate it to your lab instructor. Then, before you exit NetBeans, clean your Lab13 project. Finally, before you logout, open a terminal window and use the cd command to enter your csci/202/labs directory. Then create a JAR file of your Lab13 project folder, using the command
jar cf Lab13Project.jar Lab13Please leave both your Lab13 project folder and Lab13Project.jar in your csci/202/labs directory for the remainder of the semester.