Почему вывод типа Java не работает для возвращаемого значения с параметризованным типом? - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть универсальный тип, который реализует универсальный интерфейс.Компилятор Java корректно выводит ограничение в параметре типа типа во всех случаях, но не может сделать это в одном случае.

См. getValue() реализацию метода в классе Generic ниже:

package test.gen.company;

public class GenericProblem {
    Generic<ISpecific> gen = new Generic<>();
    //compiler has no problems here
    ISpecific val = gen.getValue();

    Generic<IMoreSpecific> gen2 = new Generic<>();
    //both of these are OK
    ISpecific val1 = gen2.getValue();
    IMoreSpecific val2 = gen2.getValue();

    //compiler won't allow this,
    //correctly complains irrelevant is not within bounds
    //Generic<Irrelevant> gen;
}

interface IGeneric<T>{
    T getValue();
    void setValue(T in);
}
interface ISpecific {}
interface IMoreSpecific extends ISpecific {}
interface Irrelevant{}
class ISpecificImplementer implements ISpecific {}

class Generic<T extends ISpecific> implements IGeneric<T> {

    @Override
    public T getValue() {
        //error: required T, found ISpecificImplementer
        return new ISpecificImplementer();

        //Unchecked cast
        //return (T) new ISpecificImplementer();
    }

    @Override
    public void setValue(T in) {
        //no complaints here, compiler knows T is ISpecific
        wantSomeB(in);
    }

    private void wantSomeB(ISpecific in){
        if (in == null) {
            throw new RuntimeException("I'm completely meaningless");
        }
    }
}

Компилятор устанавливает тип параметра в setValue(T in) в T extends ISpecific на основе параметра типа Genericно он не может установить тип T в T getValue()

Когда я использую приведение к T в getValue(), он затем жалуется на непроверенное приведение.

Почему вывод типа работает для установщика, а не для получателя?

1 Ответ

0 голосов
/ 22 февраля 2019

T в Generic<T extends ISpecific> допускается равным любому типу, расширяющему ISpecific.

Это означает, что может быть ISpecificImplementer или может быть другим подходящим типом.Выбор T не зависит от способа выбора;все зависит от того, что создает экземпляр Generic<T>.

Внутри getValue() вы пытаетесь вернуть ISpecificImplementer.Теперь T может быть ISpecificImplementer, или это может быть другой тип, который не совместим.Так что требуется актерский состав.А приведение к универсальному типу генерирует предупреждение, потому что оно обходит безопасность типов, которую должны обеспечить универсальные типы.

Предположим, что SomeOtherType - это другой класс, реализующий ISpecific.Если вы создадите экземпляр Generic<SomeOtherType> и позвоните getValue(), вы получите исключение при использовании, потому что getValue() должно вернуть SomeOtherType, но на самом деле попробуйте и верните ISpecificImplementer.Вот почему есть предупреждение о компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...