Объявление метода, возвращающего общий подтип из декларирующего типа

1

Я пытаюсь создать метод в фабричном классе. Возврат подтипа должен быть того же типа, что и объявленный аргумент.

Объявление метода сработало, но когда я пытаюсь использовать, метод не возвращает ожидаемый тип.

Вот пример, иллюстрирующий мою проблему:

import java.util.HashMap;

/**
 *
 * @author Marcos Martinewski Alves
 */
public class FooParserFactory {

    private static final HashMap<Class<? extends Foo>, FooParser<? extends Foo>> fooParsers = new HashMap();

    public static FooParser<? extends Foo> getFooParser(Class<? extends Foo> cls) {
        initParsers();
        FooParser<? extends Foo>  parser = fooParsers.get(cls);
        if (parser == null) {
            throw new RuntimeException("FooParser not found for class "+cls);
        }
        return parser;
    }

    private static void initParsers() {
        if (fooParsers.isEmpty()) {
            // populate fooParsers hashmap
        }
    }

}

Интерфейс foo

public interface Foo {

}

Реализация foo

public class FooImpl implements Foo {

}

FooParser

public interface FooParser<T extends Foo> {

    public T parse(Object object);

}

И где возникает проблема

public class FooParserUsage {

    public void useFooParser(Object source) {
        FooImpl fooImpl = FooParserFactory.getFooParser(FooImpl.class).parse(source); // here
    }

}

Я использую NetBeans IDE 8.1, и я получаю следующую ошибку:

несовместимые типы: CAP # 1 не может быть преобразован в FooImpl, где CAP # 1 является переменной типа frash CAP # 1 расширяет объект от захвата?

Есть ли способ сделать что-то подобное?

Спасибо заранее

Теги:
generics

1 ответ

2
Лучший ответ

Просто потому что <? extends Foo> <? extends Foo> выглядит так же, как <? extends Foo> <? extends Foo> не означает, что они совместимы :-)

Вы можете попытаться переформулировать это следующим образом:

public static <T extends Foo> FooParser<T> getFooParser(Class<T> cls) {
//            ^^^^^^^^^^^^^^^           ^                     ^
//            introduce a type       now these two are "compatible"
//            variable
    initParsers();

    // This line will however require a cast. Judge for yourself if it is safe.
    FooParser<T> parser = (FooParser<T>) fooParsers.get(cls);
    if (parser == null) {
        throw new RuntimeException("FooParser not found for class " + cls);
    }
    return parser;
}
  • 0
    Я был потерян, объявив Т. Это сработало просто отлично. Спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню