Skip to content

Commit bb7ffe9

Browse files
committed
docs(generics): add detailed explanation and examples for lower-bounded wildcards (? super T)
WHAT: - Introduced the concept of lower-bounded wildcards using `? super T`. - Explained syntax (`? super T` → "unknown type that is a superclass of T"). - Added examples demonstrating how lists declared with lower bounds can safely accept elements of a specific type or its subclasses. - Covered real-world use cases like adding elements to collections and consumer-producer patterns. - Documented restrictions (cannot retrieve specific elements beyond `Object`, cannot add unrelated types). WHY: - Lower-bounded wildcards are often confusing for developers compared to upper-bounded wildcards. - They provide flexibility when consuming (writing to) collections while preserving type safety. - Understanding their limitations helps avoid runtime errors and improves correct API design. DETAILS: - `addNumbers(List<? super Integer>)` → accepts `List<Integer>`, `List<Number>`, or `List<Object>`. - `addToCollection(List<? super Number>)` → allows adding `Integer` and `Double` since both extend `Number`. - `printNumbers(List<? super Integer>)` → demonstrates safe reading (but only as `Object`). - Restrictions documented: - Cannot safely retrieve elements except as `Object`. - Cannot add unrelated types like `String` when bound is `? super Number`. BENEFITS: - Encourages correct use of the PECS principle (Producer Extends, Consumer Super). - Provides safe and flexible ways to handle collections when the exact type is unknown but bounded by a lower limit. - Enhances clarity on when to use `? super` vs `? extends`. REFERENCE: - PECS Principle: - Producer → `? extends T` (read-only, covariant). - Consumer → `? super T` (write-only, contravariant). Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent 9c215df commit bb7ffe9

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
Lower-bounded wildcards are a feature of Java generics that allow us to specify that a type must be a supertype of a
2+
given class.
3+
4+
They are written using the ? super syntax.
5+
6+
This helps when you want to define a method or collection that can operate on objects of a given type or any of its
7+
supertypes.
8+
9+
Let’s break down lower-bounded wildcards, starting from the basics and moving towards more advanced topics.
10+
11+
Basics of Lower-Bounded Wildcards:
12+
Lower-bounded wildcards restrict the type of the argument to a class and its supertypes (ancestors).
13+
14+
The syntax ? super T means "some unknown type that is a superclass of T."
15+
16+
For example, List<? super Integer> can accept Integer, Number, or Object (since Integer is a subclass of Number,
17+
which is a subclass of Object).
18+
19+
public static void addNumbers(List<? super Integer> list) {
20+
list.add(10);
21+
list.add(20);
22+
}
23+
24+
In the code above, addNumbers() accepts a List that can hold any type which is a supertype of Integer.
25+
This means you can pass a List<Integer>, List<Number>, or List<Object> to this method.
26+
27+
Use Cases of Lower-Bounded Wildcards:
28+
29+
Adding to a Collection: Lower-bounded wildcards are useful when you want to add objects to a collection.
30+
You can add objects of the specified type or any of its subclasses.
31+
Consumer-Producer Pattern: Lower-bounded wildcards are also used in the consumer-producer pattern,
32+
where a method consumes values but does not produce them.
33+
34+
The method can accept objects that are supertypes of a certain type, so that it can safely add elements to the collection.
35+
36+
public static void addToCollection(List<? super Number> list) {
37+
list.add(1); // Integer (subclass of Number)
38+
list.add(1.5); // Double (subclass of Number)
39+
}
40+
41+
In this case, list can be a List<Number> or a List<Object>.
42+
43+
You can add both Integer and Double because both are subclasses of Number.
44+
45+
public static void printNumbers(List<? super Integer> list) {
46+
for (Object obj : list) {
47+
System.out.println(obj);
48+
}
49+
}
50+
51+
Here, you can pass a List<Integer>, List<Number>, or List<Object>, and it will print all the elements in the list,
52+
regardless of the specific type.
53+
54+
Restrictions with Lower-Bounded Wildcards:
55+
56+
Lower-bounded wildcards have some limitations that you need to be aware of:
57+
58+
Cannot Retrieve Specific Elements: When using lower-bounded wildcards, you lose the ability to retrieve elements of a
59+
specific type because you don’t know the exact type at runtime.
60+
61+
Cannot Add Subtypes Outside of Bounds: You cannot add elements to the list if they are not compatible with the lower bound.
62+
63+
public static void processList(List<? super Number> list) {
64+
// We cannot retrieve a specific type from the list.
65+
Object obj = list.get(0); // This is the only safe type to retrieve.
66+
}
67+
68+
Since you only know that the list can hold objects of type Number or its supertypes,
69+
retrieving an element from the list will return an Object.
70+
71+
public static void invalidAddition(List<? super Number> list) {
72+
// list.add("String"); // Compilation error
73+
}
74+
75+
In the code above, trying to add a String will result in a compilation error because String is not a subtype of Number.

0 commit comments

Comments
 (0)