Generic Classes
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 54 of 87.
Now that you understand why generics are useful, let's create your own generic class. A generic class declares one or more type parameters in angle brackets after the class name, which can then be used throughout the class.
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}The T is a type parameter—a placeholder that gets replaced with an actual type when you create an instance. You can use any name, but single uppercase letters are conventional: T for Type, E for Element, K for Key, V for Value.
When instantiating a generic class, you specify the actual type in angle brackets:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // No casting needed
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();Notice the <> (diamond operator) on the right side—Java infers the type from the declaration. You can also use multiple type parameters for classes that need to work with more than one type:
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> pair = new Pair<>("age", 25);Challenge
EasyLet's build a gift registry system that showcases the power of generic classes. You'll create a flexible storage system that can hold any type of gift item, plus a registry that pairs gift names with their details using multiple type parameters.
You'll organize your code across three files:
GiftBox.java: Create a generic class that can wrap any type of gift. YourGiftBox<T>should have a private fielditemof typeTand a private fieldwrapped(boolean) that starts asfalse. Include a constructor that accepts the item, agetItem()method that returns the item, awrap()method that sets wrapped to true, and anisWrapped()method that returns the wrapped status. Add agetStatus()method that returns either[item] (wrapped)or[item] (unwrapped)depending on the wrapped state.Registry.java: Create a generic class with two type parameters that pairs a recipient with their gift. YourRegistry<K, V>should have private fieldsrecipientof typeKandgiftof typeV. Include a constructor that accepts both values, getter methodsgetRecipient()andgetGift(), and agetEntry()method that returns:[recipient] -> [gift]Main.java: Bring your gift registry to life! You'll receive three inputs: a recipient name (String), a gift description (String), and a gift value (integer representing dollars).First, create a
GiftBox<String>containing the gift description. Wrap it using thewrap()method, then print its status.Next, create a
GiftBox<Integer>containing the gift value (representing a gift card amount). Don't wrap this one—print its status to show it's unwrapped.Finally, create a
Registry<String, String>pairing the recipient name with the gift description, and print the registry entry.
You will receive three inputs in order: recipient name, gift description, and gift value (as an integer).
Notice how the same GiftBox class works seamlessly with both String and Integer types—that's the beauty of generics! And the Registry class demonstrates how multiple type parameters let you create flexible pairings between any two types.
Cheat sheet
A generic class declares one or more type parameters in angle brackets after the class name, which can be used throughout the class:
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}The T is a type parameter—a placeholder replaced with an actual type when creating an instance. Common conventions use single uppercase letters: T for Type, E for Element, K for Key, V for Value.
When instantiating a generic class, specify the actual type in angle brackets:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // No casting needed
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();The <> (diamond operator) allows Java to infer the type from the declaration.
Use multiple type parameters for classes that work with more than one type:
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> pair = new Pair<>("age", 25);Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String recipientName = scanner.nextLine();
String giftDescription = scanner.nextLine();
int giftValue = scanner.nextInt();
// TODO: Create a GiftBox<String> containing the gift description
// TODO: Wrap it using the wrap() method
// TODO: Print its status using getStatus()
// TODO: Create a GiftBox<Integer> containing the gift value
// TODO: Don't wrap this one - print its status (should show unwrapped)
// TODO: Create a Registry<String, String> pairing recipient with gift description
// TODO: Print the registry entry using getEntry()
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System