← Back to Advanced Java Course | Chapter 1: Generics | Lesson 1 of 4

Java Generics Introduction

Generics let you write code that works with different types while keeping it safe, like a box labeled 'holds only apples'. Java then stops you from putting in the wrong kind of thing.
Syntax
java
// generic type parameter T
class ClassName<T> { }
List<Type> list = new ArrayList<>();

What are Generics?

Generics are a powerful feature in Java that let you write classes, interfaces, and methods where the data type is passed in as a parameter instead of hard-coded. This gives you strong, compile-time type safety, catching type mismatches long before your code ever runs.

Example: What are Generics?

java
// Define the class Main
public class Main {
	// Define the class Box
	static class Box<T> {
		private T value;
		Box(T value) { this.value = value; }
		T get() { return value; }
	}
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new Box object and store it in box
		Box<String> box = new Box<>("Hello");
		// Print a line to the console
		System.out.println(box.get());
	}
}

Type Safety Benefits

Before Generics, you could store any object in a collection like ArrayList, which often caused runtime ClassCastExceptions when you pulled an item out expecting one type but got another. Generics solve this by having the compiler catch that mismatch at compile-time instead, well before the code ships.

Example: Type Safety Benefits

java
import java.util.ArrayList;
import java.util.List;
public class Main {
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		list.add("Apple");
		// list.add(42); // would not compile -- caught by the compiler, not at runtime
		String item = list.get(0);
		System.out.println(item);
	}
}

Eliminating Manual Casting

Without Generics, retrieving elements from a collection required explicit, manual type casting on every access, which was verbose and error-prone. Generics eliminate this overhead entirely, letting the compiler insert and verify the cast automatically behind the scenes.

Example: Eliminating Manual Casting

java
import java.util.ArrayList;
import java.util.List;
public class Main {
	public static void main(String[] args) {
		List<String> names = new ArrayList<>();
		names.add("Riya");
		String name = names.get(0); // no manual cast needed, compiler inserts it
		System.out.println(name);
	}
}

Standard Library Generics

The standard Java Collections Framework, including List, Set, and Map, uses Generics heavily throughout its API. This ensures the data flowing through your application stays structured and type-safe from the moment it's stored to the moment it's read back out.

Example: Standard Library Generics

java
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new ArrayList object and store it in list
		List<String> list = new ArrayList<>();
		// Create a new HashSet object and store it in set
		Set<Integer> set = new HashSet<>();
		Map<String, Integer> map = new HashMap<>();
		list.add("data");
		set.add(1);
		map.put("key", 100);
		// Print a line to the console
		System.out.println(list.get(0) + " " + set.contains(1) + " " + map.get("key"));
	}
}

Generic Naming Conventions

By convention, type parameters are named using single uppercase letters so they're instantly recognizable as placeholders rather than real classes. Common naming parameters include T (Type), E (Element), K (Key), and V (Value), and following this convention makes unfamiliar generic code much easier to read.

Example: Generic Naming Conventions

java
// Define the class Main
public class Main {
	// Define the class Pair
	static class Pair<K, V> {
		K key; V value;
		Pair(K key, V value) { this.key = key; this.value = value; }
	}
	static <T> void printItem(T item) {
		// Print a line to the console
		System.out.println(item);
	}
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new Pair object and store it in p
		Pair<String, Integer> p = new Pair<>("age", 25);
		printItem(p.key + "=" + p.value);
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using primitive types as type arguments, like Box<int>, which does not compile because generics need reference types; use Box<Integer>.
  2. Using a raw type such as Box b = new Box(5);, which loses type safety and brings back the casting and ClassCastException problems generics were meant to prevent.
  3. Assuming List<String> can be assigned to List<Object> because String is an Object, which is a compile error since generics are not covariant.
🔒

Chapter Quiz — Complete all 4 topics to unlock

0/4 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.