Подтвердить что ты не робот

Вывод типа дженериков Java 7: возвращаемое значение vs аргумент метода

Почему компилятор способен правильно вывести параметр типа String в случае возвращаемого типа функции.

public class Generics {
    private static List<String> function() {
        return new ArrayList<>();
    }
}

но он терпит неудачу, если тип для вывода - параметр метода:

public class Generics {
    public static void main(String[] args) {
        method(new ArrayList<>());
    }    

    private static void method(List<String> list) {

    }
}

Ошибка в этом случае:

The method method(List<String>) in the type Generics is not applicable 
for the arguments (ArrayList<Object>)
4b9b3361

Ответ 1

Это одно из мест, где вывод типа еще не работает должным образом.

К сожалению, это поведение абсолютно корректно и соответствует.

Хорошей новостью является то, что Java 8 будет включать улучшенный вывод типа (JEP 101), поэтому ситуации как это следует компилировать так же, как вы ожидали бы этого:

Кажется разумным, что компилятор должен иметь возможность вывести тип, когда результат такого вызова общего метода передается другому методу [...].

К сожалению, это не разрешено в JDK 5/6/7 - единственный доступный для программиста вариант - использовать явный аргумент типа.

Помимо прямых улучшений (например, ситуаций, подобных тем, которые вы упомянули здесь), это изменение также необходимо для более эффективного использования Lambdas (JEP 126) (т.е. без необходимости вводить много информации о типе).

Ответ 2

Раздел вывод аргументов неразрешенного типа в JLS довольно сложный, но я понимаю, что алмаз первого случая встречается в месте, где он подвергается а во втором случае это происходит в преобразовании вызова метода, которое следует за разными правилами.