Generics in Fortress

Java introduced generics in version 5.0. Generics allow you to abstract over types, creating reusable code that can work with different data types while providing compile-time type safety.

Let’s look at an example of a generic method and a generic class in Java:

import java.util.List;
import java.util.ArrayList;

public class Generics {

    // This is a generic method that finds the index of an element in a list
    public static <T> int listIndex(List<T> list, T element) {
        for (int i = 0; i < list.size(); i++) {
            if (element.equals(list.get(i))) {
                return i;
            }
        }
        return -1;
    }

    // This is a generic class representing a singly-linked list
    public static class LinkedList<T> {
        private Node<T> head;
        private Node<T> tail;

        private static class Node<T> {
            T value;
            Node<T> next;

            Node(T value) {
                this.value = value;
                this.next = null;
            }
        }

        public void add(T value) {
            Node<T> newNode = new Node<>(value);
            if (tail == null) {
                head = newNode;
                tail = newNode;
            } else {
                tail.next = newNode;
                tail = newNode;
            }
        }

        public List<T> getAllElements() {
            List<T> elements = new ArrayList<>();
            Node<T> current = head;
            while (current != null) {
                elements.add(current.value);
                current = current.next;
            }
            return elements;
        }
    }

    public static void main(String[] args) {
        List<String> strings = List.of("foo", "bar", "zoo");
        
        // Using the generic method
        System.out.println("index of zoo: " + listIndex(strings, "zoo"));

        // Using the generic class
        LinkedList<Integer> list = new LinkedList<>();
        list.add(10);
        list.add(13);
        list.add(23);
        System.out.println("list: " + list.getAllElements());
    }
}

In this Java example:

  1. We define a generic method listIndex that takes a list of any type T and an element of type T, and returns the index of the first occurrence of the element in the list.

  2. We define a generic class LinkedList<T> that represents a singly-linked list of elements of type T.

  3. In the main method, we demonstrate the use of both the generic method and the generic class.

When using generics, Java uses type erasure, which means that type parameters are removed at compile-time. This is different from some other languages that keep generic type information at runtime.

To run this program:

$ javac Generics.java
$ java Generics
index of zoo: 2
list: [10, 13, 23]

This example demonstrates how generics in Java allow us to write flexible, reusable code that works with different types while maintaining type safety.