How to Declare a Generic Class in Java: A Comprehensive Guide

Introduction to Generics in Java

Generics in Java allow developers to create classes, interfaces, and methods that operate on specified types, enhancing code reusability and type safety. By using generics, you can write more flexible and maintainable code. This guide will explore how to declare a generic class in Java, its benefits, and provide practical examples.

What is a Generic Class?

A generic class is a class that can work with any data type. When you define a generic class, you specify one or more type parameters in angle brackets. These type parameters can then be used as placeholders for the actual data types that will be used when creating an instance of the class.

Why Use Generic Classes?

  1. Type Safety: Generics enforce compile-time type checking, reducing the risk of ClassCastException at runtime.
  2. Code Reusability: A single generic class can work with multiple data types, reducing code duplication.
  3. Cleaner Code: Generics can help avoid casting and improve code readability.

Declaring a Generic Class

To declare a generic class in Java, follow these steps:

Syntax

class ClassName<T> {
    // Class body
}
  • ClassName is the name of the class.
  • <T> is a type parameter that acts as a placeholder for a data type.

Example 1: Basic Generic Class

Let’s start with a simple example of a generic class that holds a single value of any type.

public class Box<T> {
    private T item;

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

    public T getItem() {
        return item;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<>();
        integerBox.setItem(10);
        System.out.println("Integer Value: " + integerBox.getItem());

        Box<String> stringBox = new Box<>();
        stringBox.setItem("Hello Generics");
        System.out.println("String Value: " + stringBox.getItem());
    }
}

Explanation of the Example

  1. Generic DeclarationBox<T> defines a generic class named Box with a type parameter T.
  2. Set and Get Methods: The setItem method allows you to set the value of type T, and the getItem method retrieves it.
  3. Creating Instances: In the main method, we create instances of Box for both Integer and String types.

Example 2: Multiple Type Parameters

You can also declare a generic class with multiple type parameters. Here’s how:

public class Pair<K, V> {
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        Pair<String, Integer> pair = new Pair<>("Age", 30);
        System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue());

        Pair<Integer, String> reversePair = new Pair<>(1, "One");
        System.out.println("Key: " + reversePair.getKey() + ", Value: " + reversePair.getValue());
    }
}

Explanation of Multiple Type Parameters

  1. Multiple ParametersPair<K, V> defines a generic class with two type parameters, K and V.
  2. Constructor: The constructor initializes the key and value.
  3. Usage: In the main method, we create instances of Pair for different types.

Bounded Type Parameters

Sometimes you may want to restrict the types that can be used as type arguments. This is where bounded type parameters come in.

Syntax

class ClassName<T extends SomeClass> {
    // Class body
}

Example 3: Bounded Type Parameters

Let’s create a generic class that only accepts subclasses of the Number class.

public class NumberBox<T extends Number> {
    private T number;

    public void setNumber(T number) {
        this.number = number;
    }

    public double doubleValue() {
        return number.doubleValue();
    }
}

public class Main {
    public static void main(String[] args) {
        NumberBox<Integer> intBox = new NumberBox<>();
        intBox.setNumber(10);
        System.out.println("Double Value: " + intBox.doubleValue());

        NumberBox<Double> doubleBox = new NumberBox<>();
        doubleBox.setNumber(5.5);
        System.out.println("Double Value: " + doubleBox.doubleValue());
    }
}

Explanation of Bounded Type Parameters

  1. Bounded DeclarationNumberBox<T extends Number> restricts T to be of type Number or its subclasses.
  2. Method Usage: The doubleValue method calls doubleValue() on the Number type, which is guaranteed to exist for all subclasses of Number.

Wildcards in Generics

Wildcards allow for more flexible usage of generics. There are three types of wildcards: unbounded, bounded above, and bounded below.

Unbounded Wildcards

The syntax for an unbounded wildcard is <?>. It can represent any type.

public void printBox(Box<?> box) {
    System.out.println("Box contains: " + box.getItem());
}

Bounded Wildcards

Bounded Above

Using <? extends T> means you can accept any type that is a subclass of T.

public void printNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}

Bounded Below

Using <? super T> means you can accept any type that is a superclass of T.

public void addNumbers(List<? super Integer> list) {
    list.add(10);
    list.add(20);
}

Conclusion

Declaring a generic class in Java is a powerful feature that allows you to create flexible and reusable code. By understanding how to define generic classes, use multiple type parameters, and work with bounded type parameters and wildcards, you can significantly enhance your programming skills. Generics help ensure type safety and reduce the likelihood of runtime errors, making your code more robust and maintainable.

Final Thoughts

As you continue to explore Java’s capabilities, consider incorporating generics into your projects to leverage their full potential. Whether you’re creating utility classes or developing complex applications, understanding generics will serve you well in your software development journey. Happy coding!

Please follow and like us:

Leave a Comment