Many reference types (e.g., classes and interfaces) are defined in terms of other types (for example, the type of their field, or the return or parameter types of their methods). Generic types allow programmers to replace references to specific types, such as String, with references to a placeholder, or parameter type. The generic type can then be parameterized with different specific types. As illustrated in this code sample, generic types allow for stronger compile-time type checking and more compact code through the elimination of casts.

/**
 * Copyright (C) 2024 by Martin Robillard. 
 * See https://codesample.info/about.html
 */
package essentials;

import java.util.Iterator;
import java.util.List;

/**
 * Represents a generic pair of objects of the same reference type.
 * 
 * @param <T> The type of both objects of this pair.
 */
class Pair<T> implements Iterable<T>
{
private final T aFirst; private final T aSecond; public Pair(T pFirst, T pSecond) { aFirst = pFirst; aSecond = pSecond; } public T first() { return aFirst; } public T second() { return aSecond; }
public Pair<String> asStrings() { return new Pair<>(aFirst.toString(), aSecond.toString()); } @Override public Iterator<T> iterator() { return List.of(aFirst, aSecond).iterator(); } } public class Generics {
@SuppressWarnings({ "unused", "unchecked", "rawtypes" })
public static void main(String[] args) { // Parameterized Pair Pair<Integer> pairOfIntegers = new Pair<>(1, 2);
int sum = pairOfIntegers.first() + pairOfIntegers.second();
for( Integer integer : pairOfIntegers ) { System.out.println(integer);
} String firstAsString = pairOfIntegers.asStrings().first(); // Raw Pair Pair rawPair = new Pair(1, "Two");
Integer element1 = (Integer) rawPair.first(); String element1AsString = (String) rawPair.asStrings().first();
} }