Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ListItemWriter<T>::getWrittenItems has bad wildcard return type #4576

Closed
commonquail opened this issue Apr 13, 2024 · 1 comment
Closed

ListItemWriter<T>::getWrittenItems has bad wildcard return type #4576

commonquail opened this issue Apr 13, 2024 · 1 comment

Comments

@commonquail
Copy link

commonquail commented Apr 13, 2024

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.

@commonquail commonquail added status: waiting-for-triage Issues that we did not analyse yet type: bug labels Apr 13, 2024
@fmbenhassine
Copy link
Contributor

Thank you for raising this. I agree, the wildcard return type has no added value. I will fix that in the upcoming release.

@fmbenhassine fmbenhassine added in: infrastructure and removed status: waiting-for-triage Issues that we did not analyse yet labels May 3, 2024
@fmbenhassine fmbenhassine added this to the 5.2.0-M1 milestone May 3, 2024
natedanner pushed a commit to natedanner/spring-projects__spring-batch that referenced this issue May 20, 2024
FBibonne pushed a commit to FBibonne/spring-batch that referenced this issue Feb 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants