Java generics allow you to create classes, interfaces, and methods that operate on different types in a type - safe manner. Wildcards are a part of generics, and the ? extends
wildcard is used to represent an unknown type that is a subtype of a specified type. For example, Collection<? extends Number>
can hold a collection of any subtype of Number
, such as Integer
, Double
, etc.
When dealing with Collection<? extends ...>
, Java has strict rules about type compatibility. A collection of a specific type cannot be directly assigned to a collection with a wildcard type if the types are not in a proper subtype relationship.
One of the most common use cases for Collection<? extends ...>
is when you want to read elements from a collection without modifying it. For example, you might have a method that takes a collection of any subtype of Number
and calculates the sum of its elements.
If you have a class hierarchy, you can use Collection<? extends ...>
to work with collections of different subtypes in a unified way. For instance, if you have a Shape
class with subclasses like Circle
and Rectangle
, you can write a method that takes a collection of any subtype of Shape
and performs some operation on each shape.
A common mistake is trying to assign a collection of a specific type to a collection with a wildcard type in an incorrect way. For example, trying to assign a List<Integer>
to a List<? extends Double>
will result in a compilation error because Integer
is not a subtype of Double
.
? extends
Another pitfall is trying to add elements to a collection declared with ? extends
. Since the exact type is unknown, Java does not allow you to add elements to such a collection, except for null
.
? extends
for Read - Only OperationsAs mentioned earlier, use ? extends
when you only need to read elements from a collection. This ensures type safety and allows you to work with collections of different subtypes.
? super
for Write - Only OperationsIf you need to add elements to a collection, use the ? super
wildcard instead. For example, Collection<? super Integer>
can accept a collection of any supertype of Integer
, and you can add Integer
objects to it.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
// Example of a method that calculates the sum of elements in a collection of any subtype of Number
public class CollectionExample {
public static double sum(Collection<? extends Number> numbers) {
double sum = 0;
for (Number number : numbers) {
sum += number.doubleValue();
}
return sum;
}
public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
// This works because Integer is a subtype of Number
double result = sum(integers);
System.out.println("Sum: " + result);
// Trying to add elements to a Collection<? extends ...> will result in a compilation error
// Collection<? extends Number> numberCollection = integers;
// numberCollection.add(4); // Compilation error
}
}
The “cannot be converted to java.util.Collection<? extends …>” error is a result of incorrect type usage in Java’s generic system. By understanding the core concepts of generics and wildcards, typical usage scenarios, common pitfalls, and best practices, you can write more robust and type - safe Java code. Remember to use ? extends
for read - only operations and ? super
for write - only operations to avoid common mistakes.
Collection<? extends ...>
?A: The ? extends
wildcard represents an unknown subtype. Since Java does not know the exact type, it cannot ensure type safety when adding elements. The only element you can add is null
.
List<Number>
to a List<? extends Integer>
?A: No, you cannot. Number
is a supertype of Integer
, not a subtype. So, a List<Number>
cannot be assigned to a List<? extends Integer>
.