Ответ 1
var
позволяет вывести тип, не обозначаемый:
var x = new Object() {
int i = 10;
};
System.out.println(x.i); // works; 'x' has the non-denotable type of the annonymous class
Поэтому теоретически это позволит вам вывести тип подстановочных знаков. Но этот текст говорит о том, что это невозможно, потому что подстановочный знак заменяется верхней границей или новой переменной захвата в выведенном типе.
Возьмем, к примеру, этот фрагмент кода:
List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;
var x = l2.get(0);
l2.add(x); // error
Здесь вместо того, чтобы тип x
был выведен на точный тип wild card, который бы скомпилировал последнюю строку. Вместо этого он выводится на верхнюю границу, которая является Object
, и вы получаете сообщение об ошибке (Eclipse):
The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (Object)
Где вы можете видеть, что тип x
является Object
.
Это часть
Это сопоставление заменяет переменные захвата верхними границами
Вторая часть
... и заменяет аргументы типа, в которых упоминаются переменные захвата с ограниченными подстановочными знаками
Говорит о такой ситуации:
List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;
var l3 = l2; // type of 'l3' is List<?>, but not the same '?' as 'l2'
l3.add(l2.get(0)); // error
Это тоже не скомпилируется, поскольку тип l3
не является тем же типом, что и тип l2
, а это означает, что тип, возвращаемый из l2.get(0)
, не является тем же типом, который требуется l3.add(...)
. Ошибка здесь:
The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (capture#3-of ?)
И вы видите, что обе переменные захвата различны, что означает, что тип l3
не является точно типом l2
, но переменная захвата типа l2
в выведенном типе заменяется шаблоном с той же границей, для который затем создает новую переменную захвата.
Итак, для типа List<capture#1-of?>
Выведенный тип - List<?>
, А затем компилятор создает новую переменную захвата для этого шаблона, что дает List<capture#2-of?>
(Хотя нумерация может работать по-разному на практике, ключ в том, что переменные захвата 2 различны).