CodeGym /Courses /JAVA 25 SELF /Generics: why they are needed, basic syntax

Generics: why they are needed, basic syntax

JAVA 25 SELF
Level 26 , Lesson 4
Available

1. The problem with “raw” collections (raw types)

A brief dip into history. Before Java 5, all collections were omnivorous: they stored Object, and the compiler didn’t check what exactly you were putting in. Want to put a string? Go ahead. A number? Why not. A cat? That too.

// Example of "raw" collections (raw types), Java before version 5
List list = new ArrayList();
list.add("Hello");
list.add(42);
list.add(new Object());

The problem surfaced when retrieving and using the value:

String s = (String) list.get(0); // OK, it's a string
String s2 = (String) list.get(1); // BOOM! ClassCastException

The compiler stays silent, and at runtime you get a ClassCastException. It’s like a box labeled “apples” that contains a cup, a banana, and a hedgehog.

Why is this bad?

  • Errors show up only at runtime.
  • Types get mixed up: you have to cast objects to the required type manually.
  • The code is less readable and more dangerous.

The solution — generics

Generics are a mechanism that lets you create classes, interfaces, and methods with type parameters. You tell a collection: “Store only strings,” and the compiler strictly enforces it.

List<String> words = new ArrayList<>();
words.add("Hello");
words.add("World");
// words.add(42); // Compilation error! Cannot add int to List<String>

Now the compiler won’t let you put anything other than strings into the list. The error is caught before the program runs.

The main idea of generics:
Provide type safety for collections (and more) so that errors are caught at compile time, not at runtime.

2. Generics syntax: what it looks like in code

Specifying a type in angle brackets

When you create a collection, specify the element type in <>:

List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
// names.add(123); // Error: cannot add a number to a list of strings

String first = names.get(0); // No cast needed!

Classics:

  • List<String> — list of strings
  • List<Integer> — list of integers
  • Set<Double> — set of floating-point numbers
  • Map<String, Integer> — key String, value Integer

Why not just write List?

You can, but you lose all the benefits of generics, and the compiler will warn you:

List list = new ArrayList(); // raw type — not recommended!
list.add("Hello");
list.add(7.5);
String s = (String) list.get(1); // Hello, ClassCastException!

Modern Java code always uses generics.

The diamond operator <>

Since Java 7 you can omit the type on the right if it’s clear from the context:

List<String> list = new ArrayList<>(); // The compiler will infer that this is <String>

3. Generics for different collections

Examples for List, Set, Map

List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);

Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Alice");
uniqueNames.add("Bob");

Map<String, Integer> ages = new HashMap<>();
ages.put("Alice", 23);
ages.put("Bob", 31);

Example with your own class

class Student {
    String name;
    int age;
    // ...
}

List<Student> students = new ArrayList<>();
students.add(new Student());

4. Useful details

Advantages of generics

Type safety. The compiler ensures that only elements of the required type get into the collection.

No need for casting. Before: String s = (String) list.get(0);. Now: String s = list.get(0);.

Code is more readable and reliable. Fewer surprises at runtime.

Limitations of generics

You can’t use primitive types. Generics work only with objects, not with primitives (int, double, boolean). Use wrapper classes: Integer, Double, Boolean.

List<Integer> numbers = new ArrayList<>();
numbers.add(10); // int is automatically converted to Integer (autoboxing)

A brief note on type erasure

In Java, generics are implemented via type erasure: after compilation, information about type parameters is erased, and at runtime the JVM doesn’t know whether it was a List<String> or just a List. This is for backward compatibility.

Consequence: you can’t check a type argument via instanceof with a specific type argument.

List<String> list = new ArrayList<>();
// if (list instanceof List<String>) { ... } // Compilation error!

Attempting to add an element of another type — compile-time error

List<String> words = new ArrayList<>();
words.add("Hello");
// words.add(123); // Compilation error: incompatible types: int cannot be converted to String

Map<String, Integer> map = new HashMap<>();
map.put("Cat", 5);
// map.put(3, "Elephant"); // Error: key must be String, value — Integer

And that’s great: errors are caught at compile time.

Not just collections

You can use generics in your own classes and methods. For example, a universal “Box”:

class Box<T> {
    private T value;

    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get());

Box<Integer> intBox = new Box<>();
intBox.set(42);
System.out.println(intBox.get());

Generics are standard in collections, but you’ll also encounter them elsewhere, for example in the Stream API and Optional.

5. Common mistakes when working with generics

Mistake #1: Using “raw” collections. A statement like List list = new ArrayList(); removes type safety. Always specify type parameters, for example List<String>.

Mistake #2: Trying to use primitives. You cannot write List<int>; use List<Integer> instead.

Mistake #3: Manual casts when reading from a collection. If you use generics, a cast like (String) list.get(i) isn’t needed. If you have to cast, you broke types somewhere.

Mistake #4: Expecting type parameters to be available at runtime. Because of type erasure you cannot check them via instanceof like List<String>.

Mistake #5: Mixing different types in one collection. If it’s declared as List<String>, don’t try to add an Integer — the compiler won’t allow it, and that’s a good thing.

1
Task
JAVA 25 SELF, level 26, lesson 4
Locked
My Digital Library Catalog 📚✍️
My Digital Library Catalog 📚✍️
1
Task
JAVA 25 SELF, level 26, lesson 4
Locked
Magical Universal Chests 📦✨
Magical Universal Chests 📦✨
1
Survey/quiz
Collections and generics, level 26, lesson 4
Unavailable
Collections and generics
Collections and generics
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION