I have the following classes:
abstract class DTO{ }
class SubscriptionDTO extends DTO { }
and the following generic method:
protected void fillList(ResultSet rs, ArrayList<? extends DTO> l)
throws BusinessLayerException {
SubscriptionDTO bs;
try {
while (rs.next()){
//initialize bs object...
l.add(bs); //compiler error here
}
} catch (SQLException e) {
e.printStackTrace();
}
}
I can't seem to understand why you can't create a generic method for filling DTO subtypes. Am I doing something wrong or is this by design? If so, is there any workaround? Thanks in advance.
You should be using <? super DTO> (or <? super SubscriptionDTO>, as Tom Hawtin - tackline points out) as the generic parameter of the ArrayList.
From item 28 of Effective Java (page 28 of the sample chapter [pdf]):
Here is a mnemonic to help you remember which wildcard type to use:
PECS stands for producer-extends, consumer-super.
In other words, if a parameterized type represents a
Tproducer, use<? extends T>; if it represents aTconsumer, use<? super T>.
In this case, l is a consumer (you are passing objects to it), so the <? super T> type is appropriate.
Imagine the following situation, with Foo extends Bar and Zoo extends Bar
List<Foo> fooList = new ArrayList<Foo>();
fooList.addAll(aBunchOfFoos());
aMethodForBarLists(fooList);
then we have the method itself:
void aMethodForBarLists (List<? extends Bar> barList) {
barList.add(new Zoo());
}
What happens here, is that, even though Zoo does extend Bar, you're trying to add a Zoo in a List<Foo>, which is explicitly made for, and only for, Foos.
This is why the Java spec disallows adding stuff into a <? extends Something> Collection - it can't be sure that, while the syntax seems right, the actual objects would allow adding stuff into the Collection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With