Skip to content

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.

Your Name(s):

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.

  1. Start by downloading the starter code for the UndoBox class:
  2. 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 named undobox inside a directory named labs inside 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.java
    

    If you don't have a labs directory, you should create it. If you don't have a undobox directory, you should create it.

    • If you do not have a working Java environment, use this link to open the activity in Codeboard: UndoBox.java
  3. Compile and run Driver.java to make sure it works as expected.

    • You should see the output as:
      Hello
      World
      Hello
      

Part 2: Using the Object Type

(10 min)

  1. Let's re-write UndoBox to store any type, instead of just strings.

    • Remember, the Object class is the super-super-super-class that sits above all other classes in Java.
    • A variable of type Object can hold a reference to any object.
  2. In UndoBox.java, change all occurrences of String to Object.

    • This will allow the UndoBox class to store any type of object.
    Hint

    You should change a total of five occurrences of String to Object.

  3. Now, UndoBox can hold any (reference) type!

    • Your code won't run just yet, but you can move on to the next step.
  1. Open Driver.java. You should see an error in main.

    • Interpret: What's the error about?
  1. The error is saying that it cannot convert an Object to a String!

  2. We need to cast the returned value to a String to fix the error.

    String item = (String) box.getItem();
    

  3. 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 item variable? What type is returned from getItem()?

      What is the relationship between a variable type and an object/instance type?

  1. At the bottom of main, create a second UndoBox instance called intBox to 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());
      ...
      
  2. Run the program again to make sure UndoBox now works for both types.

  1. Now, let's try to break it!
    • At the bottom of your main method, write code to try storing a String into the intBox.
    • Does it work?

      Think: Is this a good thing? Why or why not?

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)

  1. Change the class definition to include a type parameter, like so:

    public class UndoBox<ItemType> {
        ...
    }
    
  2. In UndoBox, change all occurrences of Object to ItemType.

  1. Now, UndoBox is a generic class that can store any type of object!

    • When you create an instance of UndoBox, it takes in a type, just like ArrayList<> or HashMap<>.
  2. Re-write main to specify the type that each UndoBox should hold when creating it.

    Hint

    How do you create an ArrayList to 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 an ArrayList to 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);
    
  1. Remove any casts in main that you added for the Object version of UndoBox.

    • Think: Why do we no longer need to cast the returned value from getItem()?

      Hint

      What type does getItem() return now? Is it different for box vs. intBox?

    • Go ahead and move on, even if your code has errors.

  1. Do you still get any errors in main?

    • You should find that you can no longer store a String in intBox.

      Think: Is this a good thing? Why or why not?

    • Remove or comment out this code to avoid the error.

  2. Run the program to make sure it works as expected.

  1. One more thing! Instead of calling the type parameter ItemType, change it to just T:

    public class UndoBox<T> {
        ...
    }
    
    • Then change all occurrences of ItemType to T.
  2. You can technically use any name you want, but T is 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:
      • T for some general type (e.g., Comparable<T>)
      • E for elements in a collection (e.g., ArrayList<E>)
      • K for keys in a map (e.g., HashMap<K, V>)
      • V for values in a map (e.g., HashMap<K, V>)
      • S, U, V, etc. for additional types
  3. 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.