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.