Ответ 1
Вы правы в стирании. Собственно, среда выполнения не знает об ограничениях. Только компилятор делает.
Общий метод, описанный ниже:
static <E, K extends E> void someMethod(K k, E[] e) {}
Я предполагал, что стирание будет выглядеть следующим образом:
static void someMethod(Object k, Object[] e) {}
Любопытно, как параметр type знает ограничения после стирания типа? Этот параметр типа K ограничен E?
Вы правы в стирании. Собственно, среда выполнения не знает об ограничениях. Только компилятор делает.
Подтвержденная ваша подпись. Однако при компиляции ограничения метода не стираются. Они кодируются в метаданных, которые используются во время компиляции (и обычно не используются во время выполнения, хотя к нему можно получить доступ через отражение *). Например, класс java.util.ArrayList<E>
имеет метод:
public E get(int index)
Что с типом стирания становится:
public Object get(int index)
Однако в вашем коде, если вы параметрируете ArrayList
с помощью String
, вам нужно будет вызвать метод get(...)
, не прибегая к результату String
, несмотря на стирание типа.
Это отличается от того, что происходит при параметризации вызова класса или метода. Предоставляемые параметризации полностью стираются во время компиляции. Например:
ArrayList<String> myList = new ArrayList<String>();
После компиляции эквивалентно:
ArrayList myList = new ArrayList();
* Доступ к этой информации во время выполнения через отражение может быть выполнен с использованием методов отражения, возвращающих экземпляры java.lang.reflect.Type
. Например, чтобы получить ограничения вашего метода во время выполнения, вы можете вызвать метод java.lang.reflect.Method
getGenericParameterTypes()
. Обработка этой возвращенной информации позволит определить ограничения во время выполнения.
Хочу отметить, что на самом деле ограничение типа
static <E, K extends E> void someMethod(K k, E[] e) {}
имеет точно такой же эффект (во время компиляции) как
static void someMethod(Object k, Object[] e) {}
Попробуйте позвонить someMethod("foo", new Integer[3])
, если вы мне не верите.
Это потому, что для компилятора допустимо выводить Object
как параметры для E
и K
(так как любой объект K
также является экземпляром Object
, а любой E[]
object также является экземпляром Object[]
(помните, что типы массивов ковариантны в Java)).
Это обычная ошибка в Java Generics. Например, метод Arrays.fill()
имеет подпись static void fill(Object[] a, Object val)
; их невозможно ограничить.