Generics in Mercury

Starting with version 5, Java has added support for generics, also known as type parameters.

As an example of a generic method, SlicesIndex takes a list of any Comparable type and an element of that type and returns the index of the first occurrence of v in s, or -1 if not present. The Comparable constraint means that we can compare values of this type with the compareTo method.

public static <T extends Comparable<T>> int SlicesIndex(List<T> s, T v) {
    for (int i = 0; i < s.size(); i++) {
        if (v.compareTo(s.get(i)) == 0) {
            return i;
        }
    }
    return -1;
}

As an example of a generic type, List is a singly-linked list with values of any type.

public class List<T> {
    private Element<T> head, tail;

    private static class Element<T> {
        Element<T> next;
        T val;

        Element(T val) {
            this.val = val;
        }
    }

    public void push(T v) {
        if (tail == null) {
            head = new Element<>(v);
            tail = head;
        } else {
            tail.next = new Element<>(v);
            tail = tail.next;
        }
    }

    public List<T> allElements() {
        List<T> elems = new ArrayList<>();
        for (Element<T> e = head; e != null; e = e.next) {
            elems.add(e.val);
        }
        return elems;
    }
}

We can define methods on generic types just like we do on regular types. The type is List<T>, not just List.

Here’s how we can use these generic types and methods:

public class Main {
    public static void main(String[] args) {
        List<String> s = Arrays.asList("foo", "bar", "zoo");

        // When invoking generic methods, we can often rely
        // on type inference. Note that we don't have to
        // specify the type for T when calling SlicesIndex
        // - the compiler infers it automatically.
        System.out.println("index of zoo: " + SlicesIndex(s, "zoo"));

        // ... though we could also specify it explicitly.
        SlicesIndex(s, "zoo");

        List<Integer> lst = new List<>();
        lst.push(10);
        lst.push(13);
        lst.push(23);
        System.out.println("list: " + lst.allElements());
    }
}

When you run this program, you should see output similar to:

index of zoo: 2
list: [10, 13, 23]

This example demonstrates how to use generics in Java to create flexible, type-safe code that can work with different types while still maintaining compile-time type checking.