Skip to content
On this page

Use generics

When using ArrayList , if the generic type is not defined, the generic type is actually Object :

java
// compiler warning:
List list = new ArrayList();
list.add("Hello");
list.add("World");
String first = (String) list.get(0);
String second = (String) list.get(1);

At this time, <T> can only be used as Object , and the advantages of generics are not used.

When we define the generic type <String> , the generic interface of List<T> becomes the strong type List<String> :

java
// no compiler warnings:
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
// No forced transformation:
String first = list.get(0);
String second = list.get(1);

When we define the generic type <Number> , the generic interface of List<T> becomes the strongly typed List<Number> :

java
List<Number> list = new ArrayList<Number>();
list.add(new Integer(123));
list.add(new Double(12.34));
Number first = list.get(0);
Number second = list.get(1);

If the compiler can automatically infer the generic type, it can omit the subsequent generic type. For example, for the following code:

java
List<Number> list = new ArrayList<Number>();

When the compiler sees the generic type List<Number> it can automatically infer that the generic type of the following ArrayList<T> must be ArrayList<Number> . Therefore, the code can be abbreviated as:

java
// You can omit the following Number, and the compiler 
// can automatically infer the generic type.:
List<Number> list = new ArrayList<>();

Generic interface

In addition to ArrayList<T> using generics, you can also use generics in interfaces. For example, Arrays.sort(Object[]) can sort any array, but the elements to be sorted must implement Comparable<T> generic interface:

java
public interface Comparable<T> {
    /**
     * Return a negative number: the current instance is smaller than parameter o
     * Return 0: The current instance is equal to parameter o
     * Returns a positive number: the current instance is larger than parameter o
     */
    int compareTo(T o);
}

String arrays can be sorted directly:

java
// sort
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] ss = new String[] { "Orange", "Apple", "Pear" };
        Arrays.sort(ss);
        System.out.println(Arrays.toString(ss));
    }
}

This is because String itself has implemented the Comparable<String> interface. If you try changing to our custom Person type:

java
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Person[] ps = new Person[] {
            new Person("Bob", 61),
            new Person("Alice", 88),
            new Person("Lily", 75),
        };
        Arrays.sort(ps);
        System.out.println(Arrays.toString(ps));
    }
}

class Person {
    String name;
    int score;
    Person(String name, int score) {
        this.name = name;
        this.score = score;
    }
    public String toString() {
        return this.name + "," + this.score;
    }
}

When we run the program, we will get ClassCastException , which means that Person cannot be converted to Comparable . We modify the code to let Person implement the Comparable<T> interface:

java
// sort
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Person[] ps = new Person[] {
            new Person("Bob", 61),
            new Person("Alice", 88),
            new Person("Lily", 75),
        };
        Arrays.sort(ps);
        System.out.println(Arrays.toString(ps));
    }
}

class Person implements Comparable<Person> {
    String name;
    int score;
    Person(String name, int score) {
        this.name = name;
        this.score = score;
    }
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }
    public String toString() {
        return this.name + "," + this.score;
    }
}

Running the above code can correctly sort by name .

You can also modify the comparison logic, for example, sort by score from high to low. Please modify the test yourself.

Summary

When using generics, replace the generic parameter <T> with the required class type, for example: ArrayList<String> , ArrayList<Number> etc.;

Types that the compiler can automatically infer can be omitted, for example: List<String> list = new ArrayList<>(); ;

When the generic parameter type is not specified, the compiler will give a warning and can only treat <T> as the Object type;

Generic types can be defined in interfaces, and classes that implement this interface must implement the correct generic type.

Use generics has loaded