Возвращаемый ограниченный тип несовместим с типом, который соответствует ограниченному - PullRequest
0 голосов
/ 12 декабря 2018

Я почти уверен, что что-то вроде этого было задано, но я не могу найти точную формулировку, так что вот так.

Если у меня есть эти три класса:

package boundedtypetest;

public class Factory {
    private class ClassA {}

    private class ClassB extends ClassA {}

    public <T extends ClassA> T create() {
        return new ClassB();
    }
}

Почему компилятор Java говорит, что T и ClassB несовместимы в методе create?

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Это потому, что T может быть любым подклассом ClassA.Для иллюстрации, скажем, у вас есть другой класс ClassC, который расширяет ClassA

class ClassC extends ClassA {
}

Теперь вы никогда не можете быть уверены, какой подкласс ClassA будет использоваться для вызова этого метода.

class Factory {
    public <T extends ClassA> T create() {
        return new ClassB();
    }
}

Здесь T может быть ClassB, ClassC и т. Д. Следовательно, вы не можете вернуть один из возможных подклассов из ClassA

Подробную информацию можно найти в этом ТА вопрос .

0 голосов
/ 12 декабря 2018

Вы создали универсальный метод, объявив T в качестве параметра типа с верхней границей.При использовании общих методов вы должны знать, что вызывающая сторона может решить, что такое T, передав явный аргумент типа в ваш метод.

class ClassC extends ClassA {}

ClassC c = new Factory().<ClassC>create();

Нет гарантии, что параметр типа, выбранный вызывающей стороной,явно или неявно, будет соответствовать типу того, что возвращается, и вы возвращаете ClassB.Компилятор не может гарантировать безопасность типов здесь, поэтому это запрещено.

Если вам не нужны обобщенные значения, удалите параметр типа из метода и объявите create, чтобы вернуть ClassB, ClassA,или Object.

Если вам нужны универсальные шаблоны, то вы должны взять параметр типа Class<T> и создать с ним экземпляр для удовлетворения компилятора.

public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions 
{
    return clazz.getConstructor().newInstance();
}
0 голосов
/ 12 декабря 2018

Проблема в том, что вы сможете хранить ClassB в другом классе, который расширяет ClassA

Например, у вас есть ClassC, который расширяет ClassA так же, как ClassBМожно ли сохранить результат create() в ClassC объекте, но метод сможет вернуть экземпляр ClassB?Вот почему вы не можете

class Factory {

    void method() {
        ClassC c = create();     //This is correct, regarding the return type of the method
    }                            // But it would allow to store ClassB in ClassC : NOPE

    public <T extends ClassA> T create() {
        return new ClassB();
    }

    private class ClassA { }

    private class ClassB extends ClassA { }

    private class ClassC extends ClassA { }
}
...