# Generics Source: https://wisconsin.twango.dev/fa24-cs300/u2-oop/generics # Generics Generics are a way to make classes and methods more flexible and reusable. They allow you to define a class or method with a placeholder for the type of data it will work with. This allows you to write code that can work with different types of data without having to rewrite it for each type. In Java, they are defined using angle brackets (``) to specify a type parameter. By default, the only methods that can be called on a generic type are those that are available to all objects (e.g., `toString()`, `equals()`, etc.). If you want to call a method that is specific to the type parameter, you need to use a [bounded type parameter](#bounded-type-parameters). ```java ## Generic Methods Generic methods are methods that can work with different types of data. For example, the following method takes an array of any type and prints each element: ```java public void printArray(T[] array) { for (T element : array) { System.out.println(element); } } ``` You can call this method with an array of any type, and it will print each element: ```java String[] stringArray = {"Hello", "World"}; Integer[] intArray = {1, 2, 3}; printArray(stringArray); printArray(intArray); ``` ## Generic Classes Classes can also be generic, allowing you to create a class that can work with different types of data. ```java public class Box { private T value; public Box(T value) { this.value = value; } public T getValue() { return value; } } ``` You can create an instance of a generic class by specifying the type parameter: ```java Box stringBox = new Box<>("Hello"); Box intBox = new Box<>(42); ``` ## Generic Interfaces Interfaces can also be generic, allowing you to define interfaces with type parameters. ```java public interface Pair { K getKey(); V getValue(); } ``` Classes that implement a generic interface must specify the type parameters: ```java public class OrderedPair implements Pair { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } ``` ## Bounded Type Parameters You can restrict the types that can be used with a generic class or method by using bounded type parameters with the `extends` keyword. This allows you to specify that the type parameter must be a class, a subclass of a certain class, or implement a certain interface. For example, the following method only accepts types that implement the `Comparable` interface: ```java public > T max(T a, T b) { return a.compareTo(b) > 0 ? a : b; } ``` This method can be called with any type that implements the `Comparable` interface: ```java Integer maxInt = max(5, 10); String maxString = max("apple", "banana"); ``` ## Wildcards Wildcards (`?`) can be used to represent an unknown type in a generic class or method. They allow you to write code that can work with any type without specifying the exact type. For example, the following method accepts a list of any type and prints each element: ```java public void printList(List list) { for (Object element : list) { System.out.println(element); } } ``` ### Bounded Wildcards You can also use bounded wildcards to restrict the types that can be used with a wildcard (higher bound). For example, the following method only accepts lists of types that extend `Number`: ```java public void printNumbers(List numbers) { for (Number number : numbers) { System.out.println(number); } } ``` This method can be called with a list of any type that extends `Number`, such as `Integer`, `Double`, or `Float`. Another example is the `super` keyword, which restricts the types to be superclasses of a certain type (lower bound). ```java public void addNumbers(List numbers) { numbers.add(1); numbers.add(2); } ``` ## Source The existing course note was retained and normalized during the merge. Related: [[u2-oop/index|Topic index]].