Learn / Programming / Java / Generics

Java · Lesson 12 of 15

Generics

Type-safe containers and methods with type parameters and bounds.

  • Intermediate
  • 14 min read
  • 3 objectives

Before this lessonLesson 11: Interfaces and Abstract Classes

What you will learn

  • Write a generic class
  • Write a generic method
  • Use bounded types

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

Generics let a class or method work with a type chosen by the caller while the compiler still checks it. That is why List<String> will not let you add an int.

A generic class

class Box<T> {
    private T value;
    Box(T value) { this.value = value; }
    T get() { return value; }
}

public class Main {
    public static void main(String[] args) {
        Box<String> s = new Box<>("hello");
        Box<Integer> n = new Box<>(42);
        String text = s.get();       // no cast needed
        System.out.println(text + " " + (n.get() + 1));
    }
}
Output
hello 43

A generic method

import java.util.List;

public class Main {
    static <T> T firstOrNull(List<T> items) {
        return items.isEmpty() ? null : items.get(0);
    }

    public static void main(String[] args) {
        System.out.println(firstOrNull(List.of("a", "b")));
        System.out.println(firstOrNull(List.<Integer>of()));
    }
}
Output
a
null

Bounded types

Restrict a type parameter with extends to use the methods of that type.

import java.util.List;

public class Main {
    static <T extends Comparable<T>> T max(List<T> items) {
        T best = items.get(0);
        for (T x : items) {
            if (x.compareTo(best) > 0) best = x;
        }
        return best;
    }

    public static void main(String[] args) {
        System.out.println(max(List.of(3, 9, 4)));
        System.out.println(max(List.of("pear", "apple", "zebra")));
    }
}
Output
9
zebra

Limits to know

  • Type parameters must be objects: use Integer, not int.
  • Generics are erased at runtime, so you cannot do new T() or instanceof List<String>.
  • List<Dog> is not a List<Animal>; use wildcards like List<? extends Animal> for read-only flexibility.
Up next · Lesson 13Lambdas and StreamsFunctional interfaces, lambdas, method references and the Stream pipeline.