но я хочу понять, почему с текущей подписью я получаю ошибки компиляции?
Ошибки обе, потому что <T>
определяется на сайте вызова.
Глядя на ошибку компиляции 1:
Java выбирает наиболее конкретно применимый метод. Можно выбрать любой из методов PrintStream.println
, которые принимают параметр ссылочного типа.
Из JLS 15.12.2.5 :
Неформальная интуиция заключается в том, чтоодин метод более специфичен, чем другой, если любой вызов, обработанный первым методом, может быть передан другому без ошибки времени компиляции.
Все, что вы можете передать println(char[])
или println(String)
также может быть передано println(Object)
, поэтому первые методы более специфичны, чем последние. Таким образом, они будут выбраны в предпочтении println(Object)
.
Однако некоторые вещи, которые могут быть переданы в println(char[])
, не могут быть переданы в println(String)
, поэтому ни один из них не является более конкретным, чем другойотсюда и неоднозначный вызов метода.
Теперь рассмотрим ошибку компиляции 2:
public <T>T getMethod (Stack<? extends Number >st)
{
return st.pop();
}
Этот метод должен быть безопасным для вызова во всех ситуациях. Вы вызываете это так:
System.out.println(t.getMethod(stackNumber));
т.е. вы рассматриваете результат просто как объект. Но вы могли бы по закону написать это на сайте вызова:
String s = t.getMethod(stackNumber);
Надеюсь, ясно, что это не удастся, потому что что-то выскочившее из стека, содержащего числа, не может быть преобразовано в String
.
Поскольку компилятор не может гарантировать, что он будет вызываться с "safe" T
, это ошибка.