#java #generics #type-bounds
#java #общие #тип-границы
Вопрос:
У меня есть класс CBound, который реализует два интерфейса IBound1 и Ibound2:
class CBound implements IBound1, IBound2 {}
У меня есть универсальный метод, который принимает в качестве параметра типа тип класса, который реализует как интерфейсы IBound1, так и Ibound2:
public static <T extends IBound1 amp; IBound2> void getData(T list) {
//Some code...
}
Я создал объект типа IBound1 с внедрением класса CBound:
IBound1 a = new CBound();
getData(a); // doesn't work
Почему obj a не работает в качестве параметра для getData() ?
Когда я меняю код с помощью :
CBound b = new CBound();
getData(b); // It works fine
Ответ №1:
Компилятор должен вывести a T
, который удовлетворяет ограничениям во время компиляции.
Когда вы передаете a
, все, что знает компилятор, это то, что a
имеет тип IBound1
. Поскольку параметр метода также T
равен , у компилятора действительно есть только два варианта T
here — IBound1
или Object
— nothing , которые удовлетворяют ограничениям.
Вы можете спросить: «Почему компилятор не делает вывод T
, что это CBound
так?» Ну, в выражении нет ничего getData(a)
, что имеет тип CBound
. Даже если мы знаем, что a
на самом деле это относится к объекту типа CBound
, читая предыдущие строки кода, компилятор не учитывает это при выводе T
. И даже если T
бы предполагалось CBound
, что это так, вы не смогли бы перейти a
к параметру типа CBound
.
В случае b
, однако, компилятор очень хорошо знает, что b
это тип CBound
(потому что вы объявили это так), поэтому он может успешно вывести T
, чтобы быть CBound
.
Комментарии:
1. Точно так, как сказал @Sweeper. Я бы просто добавил, что когда компилятор статически анализирует ваш код, он не знает
a
CBound
, что это динамический тип объекта, он просто знает статический типIBound1
. Это сработало бы, если бы вы набрали его.getData((CBound) a)
2. » … вы не сможете передать a параметру типа CBound» — я не понял это хорошо
3.
a
имеет типIBound1
(насколько это касается компилятора). ЕслиT
бы это былоCBound
так, тип параметра ofgetData
CBound
тоже был бы. Вы не можете передать выражение параметру, если тип этого параметра является подтипом выражения. Например, как вы не можете передать aList
принимающему методуArrayList
.