Activity 2: UndoBox
Learning Objectives:
- Re-write an existing class to use Java generics
- Use the Object type to store values of any type
- Use type parameters in a class to make the class generic
Time to Complete: 25 minutes
Submission: Submit individual PDF to Canvas
Instructions:
For these activities, follow the steps closely. Your goal is to complete all parts of the activity within the time provided.
If a section is hidden behind a "Continue" button, you should make sure that you have completed the previous sections and answered any questions before moving on. Do not skip ahead or reveal any solution until you have completed the previous steps.
Collaboration Encouraged
I encourage you to work with a partner for in-class activities! Feel free to divvy up roles, compare solutions, and learn from each other.
If the assignment requires you to submit your work, make sure to include the names of all team members in the submission.
Part 1: Getting Started
(5 min)
Your goal is to code a class called UndoBox that stores values and allows you to undo any changes.
- Start by downloading the starter code for the
UndoBoxclass: -
Open the files in a Java IDE (e.g., VS Code, IntelliJ IDEA, Eclipse, etc.)
- You may first need to create a new Java project and add the file to the project. (NOT needed for VS Code)
- You may need to move the files to the correct directory in your project.
Important: Package Declaration
The files have the package declaration
package labs.undobox;. This means that the files should be placed in a directory namedundoboxinside a directory namedlabsinside your source/project directory.For example, if your source/project directory is
src, you should have a directory structure like this:src/ ├── labs/ │ └── undobox/ │ ├── Driver.java │ └── UndoBox.javaIf you don't have a
labsdirectory, you should create it. If you don't have aundoboxdirectory, you should create it.- If you do not have a working Java environment, use this link to open the activity in Codeboard: UndoBox.java
-
Compile and run
Driver.javato make sure it works as expected.- You should see the output as:
Hello World Hello
- You should see the output as:
Part 2: Using the Object Type
(10 min)
-
Let's re-write
UndoBoxto store any type, instead of just strings.- Remember, the
Objectclass is the super-super-super-class that sits above all other classes in Java. - A variable of type
Objectcan hold a reference to any object.
- Remember, the
-
In
UndoBox.java, change all occurrences ofStringtoObject.- This will allow the
UndoBoxclass to store any type of object.
Hint
You should change a total of five occurrences of
StringtoObject. - This will allow the
-
Now,
UndoBoxcan hold any (reference) type!- Your code won't run just yet, but you can move on to the next step.
-
Open
Driver.java. You should see an error in main.- Interpret: What's the error about?
-
The error is saying that it cannot convert an
Objectto aString! -
We need to cast the returned value to a
Stringto fix the error.String item = (String) box.getItem(); -
Run the program to make sure it works as expected.
-
Think: Why does the cast needed? Why does it work?
Hint
What is the type of the
itemvariable? What type is returned fromgetItem()?What is the relationship between a variable type and an object/instance type?
-
-
At the bottom of
main, create a secondUndoBoxinstance calledintBoxto store an integer.-
Also write some test code to call methods and print out the item, similar to the existing code.
Solution
UndoBox intBox = new UndoBox(1701); System.out.println(intBox.getItem()); ...
-
-
Run the program again to make sure
UndoBoxnow works for both types.
- Now, let's try to break it!
- At the bottom of your
mainmethod, write code to try storing aStringinto theintBox. -
Does it work?
Think: Is this a good thing? Why or why not?
- At the bottom of your
Takeaway
We can use the Object type to make our class work with any type, but we need to cast any returned values to the correct type! Using the Object type also means that we lose a little bit of type safety.
We will typically not use the Object type in this way (because there's a better method), but it's good to know how it works!
Part 3: Using Type Parameters
(10 min)
-
Change the class definition to include a type parameter, like so:
public class UndoBox<ItemType> { ... } -
In
UndoBox, change all occurrences ofObjecttoItemType.
-
Now,
UndoBoxis a generic class that can store any type of object!- When you create an instance of
UndoBox, it takes in a type, just likeArrayList<>orHashMap<>.
- When you create an instance of
-
Re-write
mainto specify the type that eachUndoBoxshould hold when creating it.Hint
How do you create an
ArrayListto hold strings?ArrayList<String> list = new ArrayList<String>();Note the syntax above! You should do something similar for
UndoBox. What about integers? How would you create anArrayListto hold integers?Hint #2
UndoBox<String> box = new UndoBox<String>("Hello");Solution
UndoBox<String> box = new UndoBox<String>("Hello"); ... UndoBox<Integer> intBox = new UndoBox<Integer>(1701);
-
Remove any casts in
mainthat you added for theObjectversion ofUndoBox.-
Think: Why do we no longer need to cast the returned value from
getItem()?Hint
What type does
getItem()return now? Is it different forboxvs.intBox? -
Go ahead and move on, even if your code has errors.
-
-
Do you still get any errors in main?
-
You should find that you can no longer store a
StringinintBox.Think: Is this a good thing? Why or why not? -
Remove or comment out this code to avoid the error.
-
-
Run the program to make sure it works as expected.
-
One more thing! Instead of calling the type parameter
ItemType, change it to justT:public class UndoBox<T> { ... }- Then change all occurrences of
ItemTypetoT.
- Then change all occurrences of
-
You can technically use any name you want, but
Tis a common convention for type parameters.Naming Conventions
By convention, type parameter names are single, uppercase letters to make it clear that they are not regular class names.
- Java also has conventions for other type parameters:
Tfor some general type (e.g.,Comparable<T>)Efor elements in a collection (e.g.,ArrayList<E>)Kfor keys in a map (e.g.,HashMap<K, V>)Vfor values in a map (e.g.,HashMap<K, V>)S,U,V, etc. for additional types
- Java also has conventions for other type parameters:
-
Again, run the program to make sure it works!
Takeaway
Using a type parameter allows us to create a generic class that works with different types. At compile-time, Java makes it so that each instance of the class is restricted to the type we specify when creating it. This allows for type safety, and we no longer need to cast!
For this class, we will focus on using type parameters to create generic classes.
Submission
For these activities, you will typically submit a PDF report to Canvas. First, click the "Export as PDF" button below.
Then, submit the PDF to Canvas. Everyone must submit their own copy to receive credit.