Lab Exercises
- Exercise 1: Use Generic classes (20 minutes)
- Exercise 2: Generics and Subtyping (20 minutes)
- Exercise 3: Wild card (20 minutes)
- Exercise 4: Define your own generic class (20 minutes)
- Exercise 5: Type erasure (20 minutes)
- Exercise 6: Interoperating with non-generic code (20 minutes)
- Homework Exercise (for people who are taking Sang Shin’s “Java Programming online course”)
Exercise 1: Use Generic classes with type parameters
(1.1) Compile time type checking through Generics
1. Create a new NetBeans project
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects.
- Click Next.
- Under Name and Location pane, for the Project Name field, type in GenericsExample1 as project name.
- For Create Main Class field, type in GenericsExample1. (Figure-1.10 below)
- Click Finish.
Figure-1.10: Create a new project
- Observe that GenericsExample1 project appears and IDE generated GenericsExample1.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated GenericExample1.java as shown in Code-1.11 below and see if you experience any compile errors. Study the code by paying special attention to the bold fonted parts.
import java.util.ArrayList; import java.util.Date; import java.util.List; public class GenericsExample1 { public static void main(String[] args) { // Notice the type declaration <Integer> for the variable ai. ArrayList<Integer> ai = new ArrayList<Integer>(10); List<String> ls = new ArrayList<String>(10); List<Object> lo = new ArrayList<Object>(10); } |
Code-1.11: GenericExample1.java
3. Observe that some lines have compile errors as shown in Figure-1.12 below.
Figure-1.12: Compile errors
4. Understand why some lines have compile errors and while others don’t by reading the following explanations.
Line #15, #16, #17 (lines that have red x boxes): These three lines of code result in compilation error – cannot find symbol, symbol: method add(..). The compilation errors are generated because Long, String, and Object types are not Integer type nor sub-type of it. In pre-J2SE 5.0, a ClassCastException would have occurred during runtime (if you are casting the extracted object to a incompatible type) not compile time. Here by using generics, you are detecting a problem during compile time.
Line #18: Note that you do not have to cast Integer type as you would have done in pre-J2SE 5.0. This is because compiler knows that ArrayList<Integer> contains only Integer’s, it is not necessary to cast an element retrieved from the ArrayList of Integer to Integer type.
Line #19 (line that has red x box): Compiler generates compile error since String is not Integer type.
Line #20: This code works since the Integer type is Object type (meaning Integer type is a sub-class of Object type).
Line #22: When you create an instance of an ArrayList class, you also specify a type argument, <String>, to tell the compiler that the ArrayList is only to be used to hold objects of type String. (String is a final class so there should not be any sub-type of it.)
Line #23: Adding an entry of String to an ArrayList of String should work fine.
Line #24, #25 (lines that have red x boxes): These two lines of code result in compilation error – cannot find symbol, symbol: method add(..). The compilation errors are generated because Integer and Date types are not String type nor subtype of it.
Line #27: When you create an instance of an ArrayList class, you also specify a type argument, <Object>, to tell the compiler that the ArrayList is only to be used to hold objects of type Object or sub-type of it.
Line #28, #29, #30, #31: Because Integer, Long, String, and Object types are all Object type of subtype of it, adding an entry of these types to an ArrayList of Object should work fine.
5. For your own exercise, do some experimentation by improvising your own code and see if they behave as you expect. A sample code is provided in Code-1.14 below.
// // Invoke various methods of a collection // List<Number> ln2 = new Vector<Number>(20); // Right click this line and select Fix Imports (Alt+Shift+F) ln2.add(0, new Integer(3)); ln2.add(1, new Long(1000L)); String s2 = new String(“passion”); ln2.add(s2); Number n2 = ln2.get(0); Integer i2 = ln2.get(0); Boolean b2 = ln2.contains(new Integer(3)); Boolean b3 = ln2.contains(s2); System.out.println(“b2=”+b2); System.out.println(“b3=”+b3); // ln2.addAll(ai2); // ln2.addAll(as2); for (Number n: ln2){ |
Code-1.14: Sample code
Summary
Exercise 2: Generics and subtyping
ArrayList<Object> ao = new ArrayList<Integer>(); |
(2.1) Experiment with sub-typing
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects.
- Click Next.
- Under Name and Location pane, for the Project Name field, type in GenericsSubtyping as project name.
- For Create Main Class field, type in GenericsSubtyping.
- Click Finish.
- Observe that GenericsSubtyping project appears and IDE generated GenericsSubtyping.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated GenericsSubtyping.java as shown in Code-2.11 below. Study the code by paying special attention to the bold fonted parts.
import java.util.ArrayList; import java.util.List; import java.util.Vector; public class GenericsSubtyping { public static void main(String[] args) { // These should work // There is still inheritance relationship between classes // There is still inheritance relationship between elements in a collection object } } |
Code-2.11: GenericsSubtyping.java
3. Observe that some lines have compile errors as shown in Figure-2.12 below.
Figure-2.12
4. Understand why some lines have compile errors and while others don’t by reading the following explanations.
Line #9, #10, #11: As we have learned in Exercise 2, when you create an instance of an ArrayList<E> class, you also specify a type argument, for example, ArrayList<Integer> in Line #9, ArrayList<String> in Line #10, and ArrayList<Object> in Line #11, to tell the compiler that the ArrayList is only to be used to hold objects of a particular type or sub-type of it. In other words, ArrayList<Object> can hold objects of Object type or sub-type of it.
Line #12, #13: (lines that have red x box): These two lines of code result in compilation error, for example, incompatible types, found: java.util.ArrayList<java.lang.String> required: java.util.ArrayList<java.lang.Object> for Line #12.
<Learning point> As it clearly indicates, you cannot assign an instance of ArrayList<String> to a variable of ArrayList<Object> type. Nor you can assign an instance of ArrayList<Integer> to a varaible of ArrayList<Object> type. In other words, an ArrayList of String is not an ArrayList of Object and an ArrayList of Integer is not an ArrayList of Object. This is very counter-intuitive to our understanding of OO concept but it is a very important aspect to remember in Generics.
Gilad Bracha (JSR-14 specification lead) explained why this assignment is not allowed in Generics in his Java Programming Language (Chapter 3: Generics and Subtyping) [2]. Basically if it had been allowed, then there would be a possibility of ClassCastException being thrown during runtime, which goes against the “type-safety” principle of Generics. Let’s take a look an example code.
List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2 lo.add(new Object()); // 3 String s = ls.get(0); // 4: attempts to assign an Object to a String! ClassCastException would have to be thrown! |
Line 1 is certainly legal. But Line 2 is not legal in Generics. If it has been allowed, then during runtime, ClassCastException would have to be thrown in Line 4. [2]
5. For your own exercise, do some experimentation by improvising your own code and see if they behave as you expect. A sample code is provided in Code-1.14 below.
// // Assignment of collection with parameter types // List<Object> lo5 = new ArrayList<Integer>(); List<Object> lo6 = new Vector<Integer>(5); Collection<Object> co1 = new Vector<String>(); // Right-click this line and select Fix Imports first Collection<Object> co2 = new ArrayList<Integer> (10); Collection<Integer> ci1 = new ArrayList<Integer> (10); |
Code-1.14: Experimentation code
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/GenericsSubtyping. You can just open it and run it.
Summary
In this exercise, you learned that ArrayList<String> is not an ArrayList<Object> and why that is the case.
Exercise 3:Wild card
(3.1) Wild card
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects.
- Click Next.
- Under Name and Location pane, for the Project Name field, type in GenericsWildcard as project name.
- For Create Main Class field, type in GenericsWildcard.
- Click Finish.
- Observe that GenericsWildcard project appears and IDE generated GenericsWildcard.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated GenericsWildcard.java as shown in Code-3.11 below. Study the code by paying special attention to the bold fonted parts.
import java.util.ArrayList; import java.util.Collection; public class GenericsWildcard { static void printCollection(Collection<Object> c){ public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<Integer>(10); } } |
Code-3.11: GenericsWildcard.java
3. Observe that some lines have compile errors as shown in Figure-3.12 below.
Figure-3.12: Compile error
4. Understand why some lines have compile errors and while others don’t by reading the following explanations.
Collection<Object> c = new ArrayList<Integer> (10); // Compilation error |
import java.util.ArrayList; import java.util.Collection; public class GenericsWildcard { static void printCollection(Collection<Integer> c){ public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<Integer>(10); } } |
Code-3.14: Use compatible type
6. Now supposed you want to pass not only a collection of Integer but also a collection of any type such as Long, Float, or String etc. How would you change the printCollection()? You know you can’t use Collection<Object> as you’ve seen in previous steps. Here is where the unknown type <?> (or it is called wildcard) comes into the picture. In order to accommodate a collection of any type, you can use unknown type <?> as shown in Code-3.15 below.
import java.util.ArrayList; import java.util.Collection; public class GenericsWildcard { static void printCollection(Collection<?> c){ public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<Integer>(10); } |
Code-3.15: Use wildcard
The code in Code-3.15 above has the same effect as the one shown in Code-3.16 below.
Collection<?> c = new ArrayList<Integer> (10); // This code works c = new ArrayList<Long> (10); // This code works c = new ArrayList<String> (10); // This code works |
Code-3.16: Usage of unknown type
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/GenericsWildcard. You can just open it and run it.
(3.2) Bounded wild card
1. Create a new NetBeans project
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects.
- Click Next.
- Under Name and Location pane, for the Project Name field, type in GenericsBoundedWildcard as project name.
- For Create Main Class field, type in GenericsBoundedWildcard.
- Click Finish.
- Observe that GenericsBoundedWildcard project appears and IDE generated GenericsBoundedWildcard.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated GenericsBoundedWildcard.java as shown in Code-3.21 below. Study the code by paying special attention to the bold fonted parts.
import java.util.ArrayList; import java.util.Collection; public class GenericsBoundedWildcard { static void printCollection(Collection<? extends Number> c){ // Bounded wildcard public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<Integer>(10); } } |
Code-3.21: GenericsBoundedWildcard.java
3. Observe that some lines have compile errors as shown in Figure-3.22 below.
Figure-3.22: Compile error
The code above has the same effect as the one shown in Code-3.23 below.
Collection<? extends Number> c = new ArrayList<Integer> (10); // This code works c = new ArrayList<Long> (10); // This code works c = new ArrayList<String> (10); // Compilation error |
Code-3.23: Usage of bounded wildcard
4. Now is the time you are going to your own experimentation. Improvise your own code and see if they behave as you expect. Code-3.24 below contains sample code you can experiment with.
Collection<? extends Number> c3; c3 = new Vector<Integer>(); c3.add(new Integer(3)); c3.add(new Long(4L)); c3 = new Vector<String>(); c3 = new Vector<Long>(); c3 = new ArrayList<Date>(); Collection<? extends Object> c4; Collection<?> c5; |
Code-3.24: Experimental code using wildcard as type argument
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/GenericsBoundedWildcard. You can just open it and run it.
Summary
Exercise 4: Define your own Generic class
So far, you have worked with generic classes that are already provided by J2SE 5.0 SDK. In this exercise, you are going to create your own Generic class and then use the class in your code.
(4.1) Create a generic class, Pair<F, S>
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects.
- Click Next.
- Under Name and Location pane, for the Project Name field, type in MyOwnGenericClass as project name.
- For Create Main Class field, type in MyOwnGenericClass.
- Click Finish.
- Observe that MyOwnGenericClass project appears and IDE generated MyOwnGenericClass.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated MyOwnGenericClass.java as shown in Code-4.11 below. Note that the code creates an object instance of Pair<Number, String>. You will define Pair<F, S> in the subsequent step.
public class MyOwnGenericClass {
public static void main(String[] args) { // Create an instance of Pair <F, S> class. Let’s call it p1. // The following line of code should generate compile error System.out.println(“first of p1 (right after creation) = ” + p1.getFirst()); // Set internal variables of p1. } |
Code-4.11: MyOwnGenericClass.java
3. Write Pair.java as shown in Code-4.12 below.
public class Pair<F, S> { F first; S second; public Pair(F f, S s) { public void setFirst(F f){ public F getFirst(){ public void setSecond(S s){ public S getSecond(){ |
Code-4.12: Pair.java
4. Build and run the project
- Right click MyOwnGenericClass project and select Run Project.
- Observe the result in the Output window. (Figure-4.14 below)
first of p1 (right after creation) = 5 second of p2 (right after creation) = Sun first of p1(after setting values) = 6 second of p1 (after setting values) = rises |
Figure-4.14: Result of running MyOwnGenericClass application
(4.2) Use wild card
public class MyOwnGenericClass {
public static void main(String[] args) { // Create an instance of Pair <F, S> class. Let’s call it p1. // Set internal variables of p1. // Create an instance of Pair <F, S> class using wildcard type arguments. // Create an instance of Pair <F, S> class using wildcard with bounded type arguments. } |
Code-4.21: MyOwnGenericClass.java
2. Build and run the project
- Right click MyOwnGenericClass project and select Run Project.
- Observe the result in the Output window. (Figure-4.24 below)
first of p1 (right after creation) = 5 second of p2 (right after creation) = Sun first of p1(after setting values) = 6 second of p1 (after setting values) = rises first of p2 = 15 second of p2 = again first of p3 = and again! second of p3 = and again! |
Figure-4.24: Result of running MyOwnGenericClass1 application
(4.3) Create another Generic class, PairExtended<F, S, T>
1. Write PairExtended.java as shown in Code-4.32 below. Study the code by paying special attention to the bold fonted parts.
public class PairExtended <F, S, T> extends Pair<F, S> {
T third; /** Creates a new instance of PairExtended */ public T getThird(){ |
Code-4.32: PrintStringsThread.java
2. Modify the MyOwnGenericClass.java as shown in Code-4.33 below. The code fragments that need to be added are highlighted in bold and blue-colored font.
public class MyOwnGenericClass {
public static void main(String[] args) { // Create an instance of Pair <F, S> class. Let’s call it p1. // Set internal variables of p1. // Create an instance of Pair <F, S> class using wildcard type arguments. // Create an instance of Pair <F, S> class using wildcard with bounded type arguments. // Create an instance of PairExtended<F, S, T> class with concrete type arguments, } |
Code-4.33: TwoStrings.java
3. Build and run the project
- Right click MyOwnGenericClass project and select Run Project.
- Observe the result in the Output window. (Figure-4.34 below)
first of p1 (right after creation) = 5 second of p2 (right after creation) = Sun first of p1(after setting values) = 6 second of p1 (after setting values) = rises first of p2 = 15 second of p2 = again first of p3 = and again! second of p3 = and again! first of PairExtended = 3000 second of PairExtended = james third of PairExtended = 7 |
Figure-4.34: Result of running MyOwnGenericClass application
(4.4) Use another generic type as a parameter
1. Modify MyOwnGenericClass.java as shown in Code-4.41 below. The code fragments that need to be added are highlighted in bold and blue-colored font.
import java.util.ArrayList;
public class MyOwnGenericClass { public static void main(String[] args) { // Create an instance of Pair <F, S> class. Let’s call it p1. // Set internal variables of p1. // Create an instance of Pair <F, S> class using wildcard type arguments. // Create an instance of Pair <F, S> class using wildcard with bounded type arguments. // Create an instance of PairExtended<F, S, T> class with concrete type arguments, // Create an instance of PairExtended<F. S, T> class with } |
Code-4.41: MyOwnGenericClass.java
2. Build and run the project
- Right click MyOwnGenericClass project and select Run Project.
- Observe the result in the Output window. (Figure-4.34 below)
first of p1 (right after creation) = 5 second of p2 (right after creation) = Sun first of p1(after setting values) = 6 second of p1 (after setting values) = rises first of p2 = 15 second of p2 = again first of p3 = and again! second of p3 = and again! first of PairExtended = 3000 second of PairExtended = james third of PairExtended = 7 first of PairExtended with ArrayList = 3000 second of PairExtended with ArrayList = james third of PairExtended with ArrayList = [6000, 7000] |
Code-4.42: Result
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/MyOwnGenericClass. You can just open it and run it.
Summary
Exercise 5: Type erasure
The two important things about type erasure are
- Assuming all code is compiled under 5.0 and uses parameterized types you can guarantee that you won’t get a ClassCastException at runtime
- There is full backwards compatibility with existing compiled code that was generated with pre-J2SE 5.0 compilers
(5.1) Type erasure example 1
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects. Click Next.
- Under Name and Location pane, for the Project Name field, type in TypeErasure as project name.
- For Create Main Class field, type in TypeErasure.
- Click Finish.
- Observe that TypeErasure project appears and IDE generated TypeErasure.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated TypeErasure.java as shown in Code-5.11 below.
import java.util.ArrayList; import java.util.Collection; import java.util.List; public class TypeErasure { static void printCollection(Collection<? extends Number> c){ public static void main(String[] args) { // Display class information of the various ArrayList instances // Check if two ArrayList instances with different type parameters // Check if two ArrayList instances with different type parameters } } |
Code-5.11: TypeErasure.java
3. Build and run the project
- Right click TypeErasure project and select Run Project.
- Observe the result in the Output window. (Figure-5.15 below)
Class of ArrayList<Integer> = class java.util.ArrayList Class of List<Integer> = class java.util.ArrayList Class of ArrayList<String> = class java.util.ArrayList Class of ArrayList = class java.util.ArrayList Do ArrayList<Integer> and ArrayList<String> share same class? true Do ArrayList<Integer> and ArrayList (raw type) share same class? true |
Figure-5.15: Result of running TypeErasure application
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/TypeErasure. You can just open it and run it.
(5.2) Type erasure example 2
1. Create a new NetBeans project
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects. Click Next.
- Under Name and Location pane, for the Project Name field, type in TypeErasure2 as project name.
- For Create Main Class field, type in TypeErasure2.
- Click Finish.
- Observe that TypeErasure2 project appears and IDE generated TypeErasure2.java is displayed in the source editor window of NetBeans IDE.
import java.util.List; import java.util.Vector; public class TypeErasure2 { public static void main(String[] args) { Class [] c4 = c3.getInterfaces(); // Right-click this line and select Fix Imports first Class c5 = c3.getSuperclass(); } |
- Right click TypeErasure2 project and select Run Project.
- Observe the result in the Output window. (Figure-5.25 below)
Class of List<Number> =class java.util.Vector Interface = interface java.util.List Interface = interface java.util.RandomAccess Interface = interface java.lang.Cloneable Interface = interface java.io.Serializable Superclass = class java.util.AbstractList |
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/TypeErasure2. You can just open it and run it.
Summary
Exercise 6: Interoperating with non-generic code
(6.1) Schedule one-time task
- Select File->New Project (Ctrl+Shift+N). The New Project dialog box appears.
- Under Choose Project pane, select Java under Categories and Java Application under Projects. Click Next.
- Under Name and Location pane, for the Project Name field, type in GenericsInteroperability as project name.
- For Create Main Class field, type in GenericsInteroperability.
- Click Finish.
- Observe that GenericsInteroperability project appears and IDE generated GenericsInteroperability.java is displayed in the source editor window of NetBeans IDE.
2. Modify the IDE generated GenericsInteroperability.java as shown in Code-6.11 below. Study the code by paying special attention to the bold fonted parts.
import java.util.LinkedList; import java.util.List; public class GenericsInteroperability { public static void main(String[] args) { List<String> ls = new LinkedList<String>(); } |
Code-6.11: GenericsInteroperability.java
3. Compile the file.
- Right click GenericsInteroperability.java and select Compile file. (Or Right click GenericsInteroperability project and select Build Project.)
- Observe the waring message below. Note that the compiler warns unchecked or unsafe operation.
Compiling 1 source file to C:\javase5generics\samples\GenericsInteroperability\build\classes Note: C:\javase5generics\samples\GenericsInteroperability\src\GenericsInteroperability.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. |
Figure-6.12: Warning message
4. Run the project
- Right click GenericsInteroperability project and select Run Project.
- Observe the runtime ClassCastException. (Figure-6.13 below) This is highly undesirable. (This is not type-safe.) Because of this reason, it is highly recommended that you do not invoke non-Generic code whenever possible.
Figure-6.13: Result of running UnGenericsInteroperability application
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/GenericsInteroperabilityWarning. You can just open it and run it.
4. Modify the GenericsInteroperability.java as shown in Code-6.14 below. The code fragment that needs to be removed (or commented out) is highlighted in bold and red-colored font while the code fragment that needs to be added is highlighted in bold and blue-colored font.
import java.util.LinkedList; import java.util.List; public class GenericsInteroperability { public static void main(String[] args) { List<String> ls = new LinkedList<String>(); } |
Code-6.14: GenericsInteroperability.java
5. You should experience the compile error, which means you were able to detect type mismatch problem during the compile time rather than during runtime. (Figure-6.15 below)
Figure-6.15: Compile time type mismatch detection
NetBeans project: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javase5generics/samples/GenericsInteroperabilityCompileError.
Summary
Homework exercise (for people who are taking Sang Shin’s “Java Programming online course”)
- Create PairExtendedAgain(F, S, T, F1) generic class by extending PairExtended(F, S, T)
- Modify Main.java class to invoke PairExtendedAgain(F, S, T, F1) class with concrete type arguments <Integer, Long, Object, Boolean>
- Build and run the project
- Zip file of the the MyMyOwnGenericClass NetBeans project. (Someone else should be able to open and run it as a NetBeans project.) You can use your favorite zip utility or you can use “jar” utility that comes with JDK as following.
- cd <parent directory that contains MyMyOwnGenericClass directory> (assuming you named your project as MyMyOwnGenericClass)
- jar cvf MyMyOwnGenericClass.zip MyMyOwnGenericClass (MyMyOwnGenericClass should contain nbproject directory)
- Captured output screen – name it as JavaIntro-javase5generics.gif or JavaIntro-javase5generics.jpg (or JavaIntro-javase5generics.<whatver graphics format>)
- Any screen capture that shows that your program is working is good enough. No cosmetic polishment is required.
- If you decide to use different IDE other than NetBeans, the zip file should contain all the files that are needed for rebuilding the project.