15

Spring Batch's ItemWriter interface is this:

write(List<? extends T> items); 

I'd like the ItemWriter to call a Service but my service has this:

process(List<T> items); 

AFAIK, Java Generics are strict about casting types within collections.

BalusC
  • 1,040,783
  • 362
  • 3,548
  • 3,513
pri
  • 1,483
  • 4
  • 19
  • 29
  • Why does your service have `process(List items)` and not `process(List extends T> items)`? – ILMTitan Oct 14 '11 at 21:30
  • 2
    Because that's what I WANT. I don't have to adhere to what Spring says. – pri Oct 15 '11 at 15:15
  • Why do you want that? Are you inserting elements into items (the only functionality you would lose by making it a wildcard)? – ILMTitan Oct 17 '11 at 15:35
  • As a Service, the signature is clean and declarative with List than a wildcard, which the service doesn't need. (Yes, useful for other cases though). – pri Oct 28 '11 at 15:59

6 Answers6

13

Just go ahead and cast it. For reading, List<? extends Foo> is certainly a List<Foo>, the cast is absolutely safe. You can wrap it with Collections.unmodifiableList() if you are paranoid.

List<? extends Foo> foos1 = ...;

@SuppressWarnings("unchecked")
List<Foo> foos2 = (List<Foo>)(List<?>)foos1;    
Bax
  • 4,070
  • 3
  • 41
  • 65
irreputable
  • 43,835
  • 9
  • 63
  • 92
7

Ensure that your method receives an object that inherits from T, and then perform a cast.

Or change the signature of your method to be equal to the write method.

Tarcísio Júnior
  • 1,229
  • 7
  • 15
5
List<? extends Foo> list1 = ...
List<Foo> list2 = Collections.unmodifiableList(list1);

Reason why list2 has to be read-only view of list1 is nicely explained in an answer of Generics : List is same as List?

Community
  • 1
  • 1
czerny
  • 13,045
  • 13
  • 64
  • 86
2

If your service allows ? extends T, then that's what the type should be. Currently, it says what's passed in must be exactly T.

Ryan Stewart
  • 120,981
  • 20
  • 172
  • 194
1

Gennerics in Java helps you only in compilation time. You can cast anything, make sure that the value is castable for the new type.

user997135
  • 29
  • 3
0

Can't you just cast it since you know that if you've got a type that extends Foo that it is a Foo?
Something like this:

write(List<? extends Foo> items) {
    //noinspection unchecked
    process( (List<Foo>) items );
}

process(List<Foo> items) {
    // ...
}
Nate W.
  • 8,891
  • 6
  • 41
  • 65