Skip to main content
Dat 2. semester
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Generics and FI

Day 2

1. Generics

The box exercise

Part 1

  1. Write a non-generic Box class:
class Box {
    private Object value;

    void put(Object value) {
        this.value = value;
    }

    Object get() {
        return value;
    }
}
  1. Test the Box class by storing and retrieving different types of objects (e.g., String, Integer, Employee). And observe the need for type casting when retrieving objects from the Box.

Part 2 - What is the problem?

  1. Identify the problems with type safety and casting when using the non-generic Box class.
Box box = new Box();
box.put("Hello");

Integer x = (Integer) box.get(); // error
  • When do we get errors? Compile time or runtime? This is where generics can help us.

Part 3 - Solution with Generics

  1. Refactor the Box class to make it generic:
class Box<T> {
    private T value;

    void put(T value) {
        this.value = value;
    }

    T get() {
        return value;
    }
}
  1. Test the generic Box class by storing and retrieving different types of objects without the need for type casting.
Box<String> stringBox = new Box<>();
stringBox.put("Hello");
String str = stringBox.get(); // No casting needed
Box<Integer> intBox = new Box<>();
intBox.put(123);
Integer num = intBox.get(); // No casting needed

2. Generic Data Storage System

In this exercise, you will create a generic data storage system using interfaces and classes. Your goal is to design a flexible solution that can store and retrieve data of various types while maintaining type safety.

1.1 Create a Generic Storage Interface: Create a generic interface called DataStorage<T> that defines methods for storing and retrieving data of type T.

interface DataStorage<T> {
    String store(T data); // return a unique ID for the stored data or the filename
    T retrieve(String source); // retrieve data from the specified source (like a file or database table or ID)
}

1.2 Implement Storage Classes: Implement three classes that implement the DataStorage interface:

  • MemoryStorage<T>: Stores data in memory.
  • FileStorage<T>: Stores data in a file.

Implement the classes using appropriate data structures (e.g., instance variable or files ).

In the first instance, you can just use a String to store the data and retrieve it. If you have time, then your implementation should ensure type safety by only allowing data of the specified type to be stored and retrieved. Hint: See this file for help on how to read and write objects to a file.

1.3 Main Application:

In the main application, create instances of each storage class and demonstrate their usage by storing and retrieving data of different types.

public class DataStorageApp {
    public static void main(String[] args) {
        DataStorage<String> memoryStorage = new MemoryStorage<>();
        memoryStorage.store("Hello, world!");
        String retrievedString = memoryStorage.retrieve(null);

        DataStorage<Employee> fileStorage = new FileStorage<>();
        String filename = fileStorage.store(new Employee("John", 30));
        Employee retrievedInt = fileStorage.retrieve(filename);
    }
}

This exercise will challenge you to design a generic solution that allows for the storage and retrieval of various types of data while maintaining type safety. It will also give you hands-on experience in working with generics in both interface declarations and class implementations.