How does Generics work in Java? Explain Upper and Lower bounds in Generics. Where to choose one?

By | March 5, 2023

Generics in Java are a way to provide type safety at compile-time and enable code reuse by allowing classes and methods to operate on a range of types rather than just one. Generics were introduced in Java 5 and are represented by angle brackets <>.

When you create a generic class or method, you define a type parameter using a placeholder name inside the angle brackets. For example, to create a generic class that can hold any type of object, you can define it like this:

public class Box<T> {

    private T value;

    public void setValue(T value) {

        this.value = value;

    }

    public T getValue() {

        return value;

    }

}

In this example, T is the type parameter. You can create an instance of this class by specifying the actual type to use for T:

Box<Integer> integerBox = new Box<>();

Box<String> stringBox = new Box<>();

Upper bounds and lower bounds are used to restrict the range of types that can be used with a type parameter. An upper bound restricts the type parameter to a specific type or any of its subtypes, while a lower bound restricts the type parameter to a specific type or any of its supertypes.

To specify an upper bound, you can use the extends keyword followed by the upper bound type

public class Box<T extends Number> {

    // …

}

In this example, T can be any type that extends Number (such as Integer, Double, Float, etc.).

To specify a lower bound, you can use the super keyword followed by the lower bound type:

public void addAll(Collection<? super T> c) {

    // …

}

In this example, the addAll method can accept any collection that is a supertype of T (such as Collection<Object> or Collection<Number>).

The choice between using an upper bound or a lower bound depends on the requirements of your code. If you need to restrict the range of types that can be used as a type parameter to a specific type or its subtypes, use an upper bound. If you need to restrict the range of types to a specific type or its supertypes, use a lower bound.

What is the difference between List<? extends T>  and  List <? super T>?

List<? extends T> denotes a list of elements of a type that extends T. This means that the list can contain elements of type T or any subtype of T. For example, if T is Number, List<? extends Number> can refer to a List<Integer>, List<Double>, List<Long>, or any other list whose element type is a subtype of Number. You can use this kind of wildcard when you want to read from a list but don’t need to write to it.

List<? super T> denotes a list of elements of a type that is a supertype of T. This means that the list can contain elements of type T or any superclass of T. For example, if T is Integer, List<? super Integer> can refer to a List<Object>, List<Number>, or List<Integer>. You can use this kind of wildcard when you want to write to a list but don’t need to read from it.

In general, you can use List<? extends T> when you want to consume elements from a list, and List<? super T> when you want to produce elements to a list.

Can you pass List<String> to a method that accepts List<Object>?

No, you cannot pass a List<String> to a method that accepts a List<Object> directly in Java. This is because of type safety and type erasure in Java’s generics.

Consider the following example:

List<String> strings = new ArrayList<>();
strings.add(“hello”);
List<Object> objects = strings; // This line is not allowed.
objects.add(1);
String s = strings.get(1); // Throws ClassCastException at runtime

Here, we create a List<String> and add a string to it. Then, we try to assign it to a variable of type List<Object>, which is not allowed because of type safety. If it were allowed, we could add an integer to the list, as shown on the third line, which would cause a ClassCastException when we try to retrieve the elements as strings.

To avoid this issue, you can use a wildcard type to represent an unknown type parameter. For example, you can use List<? extends Object> or List<?> to accept any type of list.

Leave a Reply

Your email address will not be published. Required fields are marked *