🎓 A1Learner
🔍
0 of 40 lessons completed

Java Generic Methods

A generic method declares its own type parameter before the return type. The method then works for every type, and the compiler infers the type from each call.

First of a text list

first takes a List<T> and answers its first element. The call passes a list of names.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static <T> T first(List<T> list) {
    return list.get(0);
  }

  public static void main(String[] args) {
    ArrayList<String> names = new ArrayList<>();
    names.add("Ana");
    names.add("Ben");
    System.out.println(first(names));
  }
}

First of a number list

The same method now takes a list of integers. T becomes Integer for this call alone, and the answer supports arithmetic.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static <T> T first(List<T> list) {
    return list.get(0);
  }

  public static void main(String[] args) {
    ArrayList<Integer> scores = new ArrayList<>();
    scores.add(40);
    scores.add(70);
    scores.add(55);
    System.out.println(first(scores));
    System.out.println(first(scores) + 5);
  }
}

Inference at the call

Both results land in typed variables. The compiler matches each variable type with the element type of the list passed in.

import java.util.ArrayList;
import java.util.List;
public class Main {
  static <T> T first(List<T> list) {
    return list.get(0);
  }

  public static void main(String[] args) {
    ArrayList<String> names = new ArrayList<>();
    names.add("Ana");
    names.add("Ben");
    ArrayList<Integer> scores = new ArrayList<>();
    scores.add(40);
    scores.add(70);
    String word = first(names);
    Integer number = first(scores);
    System.out.println(word);
    System.out.println(number);
  }
}

Example

import java.util.ArrayList;
import java.util.List;
public class Main {
  static <T> T first(List<T> list) {
    return list.get(0);
  }

  public static void main(String[] args) {
    ArrayList<String> names = new ArrayList<>();
    names.add("Ana");
    names.add("Ben");
    ArrayList<Integer> scores = new ArrayList<>();
    scores.add(40);
    scores.add(70);
    ArrayList<Double> prices = new ArrayList<>();
    prices.add(9.5);
    prices.add(4.5);
    System.out.println(first(names));
    System.out.println(first(scores) + 10);
    System.out.println(first(prices));
  }
}

Key points

  • The <T> before the return type declares the type parameter of the method.
  • The compiler infers T from the argument, so call sites write no type.
  • One first method answers the first element of a string list and of a number list.
  • A generic method can live on a plain class that is not generic itself.

In this example, one first method serves three list types in a single program. Inference fills T separately for each call, so each answer arrives in its own type.

Note

A generic method can also be called with an explicit type, but inference makes that rare.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

In the call first(names), where names is a List<String>, how does the compiler know what T is?