Description
Spring Batch 5.1.1's ListItemWriter<T>::getWrittenItems
has the bounded wildcard generic return type List<? extends T>
. It is evident from the field's type, List<T>
, that the method return type's bounded wildcard contributes nothing of value, but besides this some constructs end up inferring the specific element type ? extends T
where only a T
can work, necessitating otherwise redundant explicit type parameter specification. This ergonomics breakage manifests trivially in AssertJ's ListAssert<ELEMENT>
, which happens to feature an API that appears counter-productively genericized, but it is easy to show with plain JDK APIs that the correct return type should be List<T>
; consider:
import java.util.*;
class T {
void foo() {
var writer = new LiWr<Element>();
var without = writer.itemsWithoutWildcard(); // List<Element>
var mutableWithout = new ArrayList<>(without); // ArrayList<Element>
mutableWithout.add(new Element());
// T.java:18: error: incompatible types: Element cannot be converted to CAP#1
// mutableWith.add(new Element());
// ^
// where CAP#1 is a fresh type-variable:
// CAP#1 extends Element from capture of ? extends Element
var with = writer.itemsWithWildcard(); // List<? extends Element>
var mutableWith = new ArrayList<>(with); // ArrayList<? extends Element>
mutableWith.add(new Element());
// T.java:25: error: incompatible types: List<CAP#1> cannot be converted to List<Element>
// List<Element> with2 = writer.itemsWithWildcard(); // List<? extends Element>
// ^
// where CAP#1 is a fresh type-variable:
// CAP#1 extends Element from capture of ? extends Element
List<Element> with2 = writer.itemsWithWildcard(); // List<? extends Element>
// ok
var with3 = writer.itemsWithWildcard();
List<Element> mutableWith2 = new ArrayList<>(with);
}
}
class LiWr<T> {
final List<T> writtenItems = new ArrayList<>();
List<? extends T> itemsWithWildcard() { return this.writtenItems; }
List<T> itemsWithoutWildcard() { return this.writtenItems; }
}
class Element {}
Effective Java 3rd Ed. item 32 also says
Do not use bounded wildcard tyeps as return types.