Generic Oddity - Eu posso inserir um valor Longo em um Map <String, String> e ele compila e não falha em tempo de execução
Dê o seguinte código:
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);
}
Não é surpreendente para mim que este código compila, mas sim que o ClassCastException ocorre na linha get em oposição à linha put acima, embora eu tenha um palpite sobre o que pode estar ocorrendo. Como os tipos genéricos são apagados durante o tempo de execução, a conversão em getValue () na verdade nunca ocorre em tempo de execução e é efetivamente convertida em Object. Se o método fosse implementado abaixo da seguinte maneira, o modelo de tempo de execução ocorreria e falharia na linha de put (conforme esperado). alguém pode confirmar isso?
class TestMethodHolder {
String getValue(Map<String, Object> dataMap, String value) {
return (String)dataMap.get(value);
}
}
Essa é uma falha ou esquisitice conhecida do uso de genéricos? É uma prática ruim usar a notação <> ao chamar métodos?
Edit: estou usando o padrão Oracle JDK 1.7_03.
Outra questão implícita de cima: é a conversão no getValue STILL original ocorrendo no tempo de execução, mas a conversão é, na verdade, para Object - ou o compilador é inteligente o suficiente para remover essa conversão de não ocorrer em tempo de execução? Isso pode explicar a diferença de onde está ocorrendo o ClassCastException que as pessoas estão percebendo ao executá-lo.