Java generics and factories

Establish:

I have some formatter interfaces:

interface Formatter<T extends AbstractItem> {
  String format(T item);
}

I have a factory to create such a formatter:

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 get the formatter & I use it:

1: Formatter formatter = Factory.create();
2: for (AbstractItem item : items) {
3:   formatter.format(item);
4: }

The item list contains only abstractitem subtypes that the formatter can handle

Question:

I received 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 the descendants of abstractitem returned by the factory:

1: Formatter<? extends AbstractItem> formatter = Factory.create();

Now the warning on line 1 disappears, but a new error appears on line 3:

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).

Therefore, if I understand it correctly, it complains that abstractitem is not a subtype of abstractitem () in type constraints Fair enough, but abstractitem is abstract, so the items I pass to the formatter always extend abstractitem of some kind

How do I explain this to the compiler? Now my solution is to use @ suppresswarnings

Solution

By declaring methods

public static Formatter<? extends AbstractItem> create()

The caller who declares this method will never know the exact type of formatter; The caller will only know that it is a formatter < x > Where x is abstractitem or its subclass Therefore, you cannot pass any instance to the returned formatter because you never know which X

It is absolutely wrong to cancel the warning here. The compiler tells you the right thing: your code is unsafe Given two subclasses of abstractitem, Foo and bar, the factory can return formatter < foo > and you can pass an instance of bar to its format method

There is a semantic problem and does not indicate what formatter your factory will return and why Either make it a concrete factory, or return formatter < x > where x is a concrete type instead of? Extension... Or you must add a parameter to provide a hint to the factory about which formatter is required, such as

public static <T extends AbstractItem> Formatter<T> create(Class<T> forItemType)

Or you turned it into

public static Formatter<AbstractItem> create()

Specifies that the returned formatter can handle various abstractitems Remember, you can still pass any subclass of abstractitem to formatter < abstractitem > because each instance of the subclass of abstractitem is still an instance of abstractitem, just like in the era before generics

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>