# 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 (`<T>`) 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 <T> 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<T> {
    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<String> stringBox = new Box<>("Hello");
Box<Integer> intBox = new Box<>(42);
```

## Generic Interfaces

Interfaces can also be generic, allowing you to define interfaces with type parameters.

```java
public interface Pair<K, V> {
    K getKey();
    V getValue();
}
```

Classes that implement a generic interface must specify the type parameters:

```java
public class OrderedPair<K, V> implements Pair<K, V> {
    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 extends Comparable<T>> 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<? extends Number> 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<? super Integer> 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]].
