Почему этот общий код в java компилируется?
public static <T> T foo(T x, T x2) {
return (T) (x + " " + x2);
}
public static void main(String args[]) {
System.out.println(foo(33, "232"));
}
Я знаю, что T получает тип, который передается в параметре.
Но здесь есть два типа.
Какой из них T?
и почему компилятор не заставляет меня иметь параметры того же типа, когда я вызываю foo?
Ответы
Ответ 1
Это законно, потому что Integer
и String
имеют общий базовый тип. T
может быть Object
, поэтому foo(T, T)
будет принимать любые два объекта. 32
может быть автобокс с Integer
, что является видом Object
. "232"
является String
, что является видом Object
.
(Как отмечалось в комментариях, для Integer
и String
существует более близкий общий базовый тип Serializable
, но принцип тот же, какой бы базовый тип не разрешал компилятор T
to.)
Ответ 2
public static <T> T foo(T x, T x2) {
return (T) (x + " " + x2);
}
Следует отметить, что во время компиляции он может выйти из строя во время выполнения:
int f = foo(1, 2);
выйдет из строя Ideone demo, потому что метод возвращает String
, а не Integer
.
Он компилируется, однако, поскольку стирание стилей означает, что T
переписывается на верхнюю границу, а именно Object
. Итак:
public static Object foo(Object x, Object x2) {
return (Object) (x + " " + x2);
}
Это хорошо, потому что результатом является String
, который является подтипом Object
.
Я предполагаю, что это всего лишь случай, когда модели дженериков ожидают вас. Вот почему я бы избегал смешивать дженерики и явное литье.