Generics in Java: Why They Are Needed and How to Use Them for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Generics in Java: Why They Are Needed and How to Use Them for Beginners



When learning Java, sooner or later you will encounter the concept of Generics. For a beginner, this may seem complicated, but in reality, it is one of the most useful tools in the language. In this article, we will break down what Generics are, why they are needed, and how to use them correctly. The material is intended for beginner developers.



What are Generics and why is it bad without them?



Generics are a Java mechanism that allows you to parameterize types. In simple terms, you can write a class, interface, or method that will work with different data types, while maintaining strict typing at compile time.



Imagine you want to create a box that can hold any item. Without Generics, you would have to use Object:



public class Box {    private Object item;

public void put(Object item) { this.item = item; }

public Object get() { return item; }}


Using such a class is a real pain:



Box box = new Box();box.put("Hello");// When retrieving, you need to explicitly cast the typeString text = (String) box.get(); // Risk of ClassCastException!


If you accidentally put a number and then try to cast it to a string, the program will crash with an error at runtime. Generics solve this problem by moving type checking to compile time.



How to use Generics: basic syntax



Let's rewrite our Box class using Generics:



public class Box<T> {    private T item;

public void put(T item) { this.item = item; }

public T get() { return item; }}


Here, <T> is the type parameter. T is a commonly used name (from the word "Type"), but you can use any letter or word: E (Element), K (Key), V (Value), etc.



Now the usage has become safe and elegant:



Box<String> stringBox = new Box<>();stringBox.put("Hello");String text = stringBox.get(); // No need for casting!

// This line will not compile:// stringBox.put(123); // Compilation error!


The compiler itself knows that stringBox only works with strings. If you try to put a number, the code won't even compile — you'll learn about the error immediately, not at runtime.



Generics in collections: where they are needed most



The most popular place to use Generics is in Java collections (List, Set, Map, and others). Before the advent of generics (in Java 5), developers struggled with ArrayList, which stored Object:



// Old style (without Generics)List list = new ArrayList();list.add("Hello");list.add(123); // This can also be added!

String item = (String) list.get(0); // FineString item2 = (String) list.get(1); // ClassCastException!


With Generics, everything is simpler and safer:



List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");// names.add(123); // Compilation error

for (String name : names) { System.out.println(name.toUpperCase()); // No casting!}


The same works for Map:



Map<String, Integer> ageMap = new HashMap<>();ageMap.put("Alice", 30);ageMap.put("Bob", 25);

int aliceAge = ageMap.get("Alice"); // Automatic unboxing to int


Bounded types and wildcards: how to make Generics flexible



Sometimes you need to restrict what types a generic can accept. Bounded type parameters are used for this purpose.



For example

Blogs

Book Recommendations