# Nachdenkzettel: Generics

## 1. Generische Klasse: `Pair`

Generics helfen dabei, Klassen zu schreiben, dass sie mit unterschiedlichen Typen arbeiten können, ohne überall `Object` zu verwenden. Dadurch wird Code typsicherer, lesbarer und oft leichter wiederverwendbar. 

Schreiben Sie eine Klasse `Pair`, die zwei Werte desselben Typs speichert.

Der folgende Code soll funktionieren:

```java
Pair<String> names = new Pair<>("Ada", "Grace");

String firstName = names.getFirst();
String secondName = names.getSecond();

Pair<Integer> points = new Pair<>(10, 20);

Integer x = points.getFirst();
Integer y = points.getSecond();
```

Die Klasse soll folgende Methoden haben:

```java
public T getFirst()
public T getSecond()
```

Die Klasse soll nicht mit `Object` arbeiten und der folgende Code soll ohne Cast funktionieren:

```java
String name = names.getFirst();
Integer point = points.getFirst();
```

Beantworten Sie kurz:

1. Warum muss die Klasse `Pair` hier generisch sein?
2. Wie sieht die Klasse `Pair` aus?
3. Was wäre schlecht, wenn `getFirst()` nur `Object` zurückgeben würde?

---

## 2. Generisches Array: `SimpleStack`

Schreiben Sie eine Klasse `SimpleStack<T>`, die intern ein Array verwendet.

Der folgende Code soll funktionieren:

```java
SimpleStack<String> texts = new SimpleStack<>(3);

texts.push("A");
texts.push("B");

String value = texts.pop();
```

Und auch dieser Code soll funktionieren:

```java
SimpleStack<Integer> numbers = new SimpleStack<>(3);

numbers.push(10);
numbers.push(20);

Integer value = numbers.pop();
```

Die Klasse soll intern ein Array verwenden:

```java
private T[] values;
```

Da Java kein direktes `new T[size]` erlaubt, können Sie im Konstruktor diese Variante verwenden:

```java
@SuppressWarnings("unchecked")
public SimpleStack(int size) {
    values = (T[]) new Object[size];
}
```

Implementieren Sie:

```java
public void push(T value)
public T pop()
```

Beantworten Sie kurz:

1. Warum ist der Stack mit `T` flexibler als ein `StringStack`?
2. Warum ist der Rückgabetyp von `pop()` hier wichtig?
3. Warum kann Java kein direktes `new T[size]` erzeugen?

---

## 3. Generische Methode: `last`

Schreiben Sie eine generische Methode `last`, die das letzte Element aus einer Liste zurückgibt.

Der folgende Code soll funktionieren:

```java
List<String> names = List.of("Ada", "Grace", "Evelyn");
String lastName = ListUtils.last(names);
```

Und auch dieser Code:

```java
List<Integer> numbers = List.of(3, 7, 9);
Integer lastNumber = ListUtils.last(numbers);
```

Die Methode soll in dieser Klasse stehen:

```java
import java.util.List;

public class ListUtils {
    // Methode hier ergänzen
}
```

Die Methode soll nicht `Object` zurückgeben. Sie soll immer den Typ der übergebenen Liste behalten.

Beantworten Sie kurz:

1. Wie sieht `last` aus und warum benötigen Sie eine generische Methode?
2. Warum ist der Rückgabetyp nicht `Object`?
3. Woher weiß der Compiler, dass bei `List<String>` ein `String` zurückkommt?
