17

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,082,665
  • 372
  • 3,610
  • 3,555
pri
  • 1,533
  • 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

15

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,260
  • 5
  • 43
  • 65
irreputable
  • 44,725
  • 9
  • 65
  • 93
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,239
  • 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
  • 15,090
  • 14
  • 68
  • 96
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
  • 126,015
  • 21
  • 180
  • 199
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
  • 39
  • 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.
  • 9,141
  • 6
  • 43
  • 65