Setup:
I have an interface for some formatters:
interface Formatter<T extends AbstractItem> {
String format(T item);
}
I have a factory creating such formatters:
public class Factory {
public static Formatter<? extends AbstractItem> create() {
switch (something) {
case SOMETHING: return new Formatter<SomeItem>() { String format(SomeItem item) {...}};
case SOMETHING_ELSE: return new Formatter<OtherItem>() { String format(OtherItem item){...}};
}
Now I use this factory to obtain the formatter & I use it:
1: Formatter formatter = Factory.create();
2: for (AbstractItem item : items) {
3: formatter.format(item);
4: }
The items
list contains only AbstractItem
subtypes that the formatter
is able to process.
Problem:
I am getting two warnings:
Line 1: Formatter is a raw type. References to generic type Formatter<T> should be parameterized.
Line 3: Type safety: The method format(AbstractItem) belongs to the raw type Formatter. References to generic type Formatter<T> should be parameterized.
OK, so I try to fix the first one: I know that the factory returns something descended from AbstractItem
:
1: Formatter<? extends AbstractItem> formatter = Factory.create();
Now the warning on Line 1 disappears, but a new error on Line 3 occurs:
Line 3: The method format(capture#3-of ? extends AbstractItem) in the type Formatter<capture#3-of ? extends AbstractItem> is not applicable for the arguments (AbstractItem).
So if I understand correctly, it's complaining that AbstractItem
is not a sub-type of AbstractItem
(as required in the type constraint <? extends AbstractItem>
). Fair enough, but AbstractItem
is abstract, so the item
I pass to the formatter
is always of some type extending AbstractItem
...
How do I explain this to the compiler? For now my solution is to go with the @SuppressWarnings
...