Введите следующий код:
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>();
HashMap<String, Object> dataMap = new HashMap<>();
dataMap.put("longvalue", 5L);
class TestMethodHolder {
<T> T getValue(Map<String, Object> dataMap, String value) {
return (T)dataMap.get(value);
}
}
hashMap.put("test", new TestMethodHolder().<String>getValue(dataMap, "longvalue"));
String value = hashMap.get("test"); // ClassCastException occurs HERE
System.out.println(value);
}
Мне неудивительно, что этот код компилируется, а скорее, что ClassCastException встречается в строке get, а не в строке put выше, хотя у меня есть обоснованное предположение о том, что может произойти. Поскольку общие типы стираются во время выполнения, приведение в getValue() на самом деле никогда не происходит во время выполнения и фактически является отличным от Object. Если метод будет реализован ниже следующим образом, тогда будет выполняться бросок времени выполнения, и он потерпит неудачу в строке ввода (как и ожидалось). Кто-нибудь может это подтвердить?
class TestMethodHolder {
String getValue(Map<String, Object> dataMap, String value) {
return (String)dataMap.get(value);
}
}
Является ли это известным недостатком или необычностью использования дженериков? Неправильно ли тогда использовать символ < > при вызове методов?
Изменить: Я использую Oracle JDK 1.7_03 по умолчанию.
Еще один подразумеваемый вопрос сверху: Является ли приведение в исходном getValue STILL происходящим во время выполнения, но приведение на самом деле является объектом Object - или компилятор достаточно умен, чтобы удалить этот прилив из-за отсутствия во время выполнения? Это может объяснить разницу в том, где происходит ClassCastException, которое люди замечают при запуске.