Last Updated:

Java Generics Guide - Description and Examples

Genrics* were added in Java 5 and are now an integral part of Java Core. If you're familiar with Java Collections version 5 or later, then I'm sure you've used generics in your programs.

*Generics/Generic types - later in the article I will use the name Generics or generics as the most used, although the correct translation is still Generic types

Using generics with collection classes is not only easy, but it also provides much more options than just specifying the type of collection. To make the process of studying generics simpler and more understandable, we will mainly use the code and comments to it.

Briefly about Generics

Starting with Java 5, the entire Collection Framework has been rewritten from scratch using Generics. Let's take a look at how generics help you use collection classes safely.

Example without generics

The code above compiles normally, but throws because we are trying to cast an object in the list to a type while one of the list items is . Starting with Java 5, the code above will be rewritten as shown below:ClassCastExceptionStringInteger

Example with generics:

Notice that at the time the list was created, we specified that the type of items in the list would be string (). So if we try to add any other type of object to the list, the program will throw a compilation error. Also note that we don't use type casting while crawling the list in the loop, which means we don't have to worry about .

StringforClassCastException

Using Generics in Interfaces and Classes

We can define our own classes and interfaces with generics. To do this, use angle brackets to specify the type of a class or interface parameter.<>

To understand this, let's create a simple class.

Without generics:

Note that when using this class, we have to cast object types, which can lead to . Now we will use generics - we will rewrite the same class but with generics.ClassCastException

With generics:

Note the method of the GenericsType class. We don't have to worry about type conversion, so we're not afraid. If we are not writing a type when we create an instance of the class, the compiler will warn you with the following message. Let's decipher this message. When we do not write a type at the time of creating an instance of the class, the type automatically becomes Object and therefore allows the use of both objects and other objects. This nullifies the advantages of generics in Java and forces the use of type conversion, that is, it will be the OldSchool class (see the code above).

main()ClassCastException"GenericsType is a raw type. References to generic type GenericsType<T> should be parameterized"StringInteger

(Although we can use the @SuppressWarnings annotation ("rawtypes") to suppress the compiler warning, but that's the topic of another article)

It should also be noted that we used Java Autoboxing.

Generics in interfaces

The interface is a great example of using Generics in interfaces.Comparable

We can take this code as an example and use generics in our interfaces and classes. We can also use several parameters, such as the . Here's an example: — cool, right? 🙂

Mapnew HashMap<String, List<String>>()

Generics: Naming Convention

The naming convention helps us understand the code and unifies it, so it needs to be followed. Generics have naming rules. These are usually uppercase letters, which easily distinguishes them from Java variables. The most commonly used type parameter names are:

  • E is an element (widely used in the Java Collections Framework, e.g. , etc.)ArrayListSet
  • K is the key (used in Map)
  • T — Type
  • B — value (used in Map)
  • S, U, V, etc. — 2nd, 3rd, 4th... type

Generics in methods and constructors

Sometimes we don't need the entire class to be parameterized. In this case, we can only use the generic type in the methods.

Let's look at this immediately using the example of a class with generics in methods.

package com.p-qc;
public class GenericsMethods {
// Generics in methods
public static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){
return g1.get().equals(g2.get());
}

public static void main(String args[]){
GenericsType<String> g1 = new GenericsType<>();
g1.set("Prologistic");

GenericsType<String> g2 = new GenericsType<>();
g2.set("str");

//here is one usage example
boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);

// but the second one is simplified
isEqual = GenericsMethods.isEqual(g1, g2);
}
}

Generics and inheritance

We know that Java inheritance allows you to assign variable A to another variable B if A is a subclass B. Thus, we could assume that any type of generic A can be assigned to generic type B, but this is not the case. Let's look at an example of a simple program.