Creating and Using Generic Classes in Java

Java generics provide a powerful way to create reusable and type-safe code. With generic classes, you can create components or data structures that can work with different data types without sacrificing type safety. In this article, we will explore how to create and use generic classes in Java.

What are Generic Classes?

Generic classes are classes that define one or more type parameters. These type parameters act as placeholders for actual types that will be specified when an instance of the class is created. This enables the class to be used with different types, providing flexibility and reusability.

Creating a Generic Class

To create a generic class, you need to declare one or more type parameters when defining the class. The type parameters are enclosed in angle brackets (< >) and can have any valid Java identifier name.

Here's an example of a generic class called Box:

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

In the above example, T is the type parameter. The type parameter T can be replaced with any valid Java type when creating an instance of Box. For example, we can create a Box for storing String objects:

Box<String> stringBox = new Box<>();
stringBox.setContent("Hello, World!");

String content = stringBox.getContent();
System.out.println(content); // Output: Hello, World!

Similarly, we can create a Box for storing Integer objects:

Box<Integer> intBox = new Box<>();
intBox.setContent(42);

int content = intBox.getContent();
System.out.println(content); // Output: 42

By using generic classes, we can ensure that the content stored in the Box is always of the specified type.

Using Multiple Type Parameters

Generic classes can have multiple type parameters. Each type parameter is separated by a comma.

Here's an example of a generic class Pair with two type parameters:

public class Pair<T, U> {
    private T first;
    private U second;

    public Pair(T first, U second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public U getSecond() {
        return second;
    }
}

We can create a Pair of String and Integer as follows:

Pair<String, Integer> nameAndAge = new Pair<>("Alice", 25);

String name = nameAndAge.getFirst();
int age = nameAndAge.getSecond();

System.out.println("Name: " + name + ", Age: " + age);
// Output: Name: Alice, Age: 25

Type Bounds

In some cases, you might want to restrict the types that can be used with a generic class. Java allows you to specify type bounds to restrict the type parameters.

For example, let's say we have a generic class ComparableBox that can only store content of types that implement the Comparable interface:

public class ComparableBox<T extends Comparable<T>> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

Now, when creating a ComparableBox, we can only use types that implement the Comparable interface:

ComparableBox<Integer> intBox = new ComparableBox<>();
intBox.setContent(42);

ComparableBox<String> stringBox = new ComparableBox<>();
// Compiler error: String does not implement Comparable interface

Conclusion

Generic classes provide a powerful way to create reusable and type-safe code in Java. By using type parameters, you can create classes that can work with different types without sacrificing type safety. With the ability to specify type bounds, you can further restrict the types that can be used with generic classes. Start leveraging the power of generic classes in your Java projects to enhance reusability and type safety.


noob to master © copyleft