Преобразование захвата было разработано, чтобы сделать подстановочные знаки (в обобщениях), ?
полезно.
Предположим, у нас есть следующий класс:
public interface Test<T> {
public void shout(T whatever);
public T repeatPreviousShout();
}
и где-то в нашем коде мы имеем,
public static void instantTest(Test<?> test) {
System.out.println(test.repeatPreviousShout());
}
Поскольку test
не является необработанным Test
и поскольку repeatPreviousShout()
в «заднем плане» возвращает ?
, компилятор знает, что существует T
, который служит параметром типа для Test
.
Это T
для некоторого неизвестного T
, поэтому компилятор удаляет неизвестный тип (для подстановочного знака он заменяется на Object
). Следовательно, repeatPreviousShout()
возвращает Object
.
Но если бы мы имели,
public static void instantTest2(Test<?> test) {
test.shout(test.repeatPreviousShout());
}
Компилятор выдаст нам ошибку, например, Test<capture#xxx of ?> cannot be applied
(где xxx
- это число, например, 337
).
Это потому, что компилятор пытается выполнить проверку безопасности типов на shout()
, но, поскольку он получил подстановочный знак, он не знает, что представляет T
, поэтому он создает заполнитель с именем capture of .
С здесь (теория и практика Java: схожу с дженериками, часть 1) , в нем четко говорится:
Преобразование захвата - это то, что позволяет
компилятор для изготовления заполнителя
введите имя для захваченного символа подстановки,
так что вывод типа может сделать вывод
будь того типа.
Надеюсь, это поможет вам.