Generics in Java

Java introduced generics in version 5.0. While Java’s implementation of generics differs from Go’s, they serve a similar purpose of providing type safety and reusability.

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

public class Generics {

    // In Java, we use <T extends Comparable<T>> to constrain the type parameter
    // to types that implement Comparable, which is similar to Go's comparable constraint.
    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;
    }

    // In Java, we can create a generic class similar to Go's List
    public static class GenericList<T> {
        private Node<T> head;
        private Node<T> tail;

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

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

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

        public List<T> allElements() {
            List<T> elems = new ArrayList<>();
            Node<T> current = head;
            while (current != null) {
                elems.add(current.val);
                current = current.next;
            }
            return elems;
        }
    }

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

        // In Java, type inference for generic methods was introduced in Java 7
        System.out.println("index of zoo: " + slicesIndex(s, "zoo"));

        // We can also specify the type explicitly
        slicesIndex(s, "zoo");

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

To run this program, save it as Generics.java, compile it, and then run it:

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

In this Java version:

  1. We’ve created a slicesIndex method that’s similar to Go’s SlicesIndex function. It uses Java’s generics with a type bound (T extends Comparable<T>) to ensure we can compare elements.

  2. We’ve created a GenericList<T> class to demonstrate generic types in Java. This is similar to Go’s List[T] struct.

  3. The push and allElements methods on GenericList<T> work similarly to their Go counterparts.

  4. In the main method, we demonstrate using these generic constructs, including type inference for method invocation.

Note that Java’s implementation of generics uses type erasure, which means that generic type information is removed at runtime. This is different from Go’s approach, which maintains type information at runtime.