Java Generics: множественное наследование в параметрах ограниченного типа

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

public class A { }
public interface I { }

Это фабричный метод:

public class F {
    public static <T extends A & I> T newThing() { /*...*/ }
}

Это компилирует все нормально.

Когда я пытаюсь использовать этот метод, следующее работает нормально:

A $a = F.newThing();

...в то время как это не работает:

I $i = F.newThing();

Компилятор жалуется:

Несоответствие границ: универсальный метод newThing() типа F не применимо для аргументов (). Выведенный тип I&A не является допустимой заменой ограниченного параметра

. Я не могу понять, почему.Четко сказано, что «newThing возвращает что-то определенного типа T, который расширяет класс A и реализует интерфейс I». При присвоении A все работает (поскольку T расширяет A), а при присвоении I нет (из-за чего?, ясно, что возвращаемая вещь является и A , и . ] an I)

Также: при возврате объекта, скажем, B типа класс B extends A реализует I, мне нужно привести его к возвращаемому типу T, хотя B соответствует границам:

<T extends A & I> T newThing() {
    return (T) new B();
}

Однако компилятор не выдает никаких предупреждений типа UncheckedCast и т.п.

Итак, мой вопрос:

  • Что здесь происходит не так?
  • Существует ли простой способ добиться желаемого поведения (т. е. присвоить значение переменной статического типа A или I), как это делается при решении проблемы возвращаемого типа путем приведения в фабричном методе?
  • Почему присваивание А работает, а I нет?

--

РЕДАКТИРОВАТЬ: Вот полный фрагмент кода, который полностью работает с использованием Eclipse 3.7, проект настроен для JDK 6:

public class F {
    public static class A { }
    public static interface I { }

    private static class B extends A implements I {  }

    public static <T extends A & I> T newThing() {
        return (T) new B();
}

    public static void main(String... _) {
        A $a = F.newThing();
        // I $i = F.newThing();
    }
}

РЕДАКТИРОВАТЬ: Вот полный пример с методами и вызовами, которые работает во время выполнения :

public class F {
    public static class A {
        int methodA() {
            return 7;
        }
    }
    public static interface I {
        int methodI();
    }

    private static class B extends A implements I {
        public int methodI() {
            return 12;
        }
    }

    public static <T extends A & I> T newThing() {
        return (T) new B();
    }

    public static void main(String... _) {
        A $a = F.newThing();
        // I $i = F.newThing();
        System.out.println($a.methodA());
    }
}
12
задан Jeff Axelrod 30 March 2012 в 02:42
поделиться