O que é raw type em Java Generics e por que devemos evitá-los?
Olá a todos! Sou um desenvolvedor Java iniciante, estou estudando generics e me deparei com um conceito estranho chamado "raw type" (tipo bruto). Até entendo que está relacionado a genéricos, mas não capto totalmente a essência.
Suponha que eu tenha este código:
```java
List list = new ArrayList(); // isso é raw type?
list.add("string");
list.add(123);
```
O compilador emite um aviso, mas o código funciona. Posso colocar qualquer coisa na lista. Mas se eu usar um tipo parametrizado:
```java
List list2 = new ArrayList<>();
list2.add("string");
// list2.add(123); // erro de compilação
```
Então o compilador reclama. Qual é a diferença? Por que raw type é considerado uma má prática? Afinal, o código funciona com ele. Ouvi dizer que raw types existem para compatibilidade reversa, mas por que usá-los em código novo? E como eles se relacionam com type erasure (apagamento de tipo)?
Por favor, dê exemplos de quando o uso de raw type pode levar a erros em runtime que não são detectados em tempo de compilação.