Tipos brutos em Java
1. Introdução
Neste tutorial rápido, vamos dar uma olhada nos tipos brutos, o que são e por que devemos evitá-los.
2. Tipos brutos
Um tipo bruto é um nome paraa generic interface or class without its type argument:
List list = new ArrayList(); // raw type
Ao invés de:
List listIntgrs = new ArrayList<>(); // parameterized type
List<Integer> é umparameterized type da interfaceList<E>, enquantoList é umraw type da interfaceList<E>.
Tipos brutos podem ser úteis ao fazer interface com código legado não genérico.
Caso contrário, porém,it’s discouraged. Isso ocorre porque:
-
Eles não são expressivos
-
Eles não têm segurança de tipo e
-
Os problemas são observados no tempo de execução e não no tempo de compilação
3. Inexpressivo
Um tipo bruto não documenta e se explica da mesma maneira que um tipo parametrizado.
Podemos facilmente inferir que um tipo parametrizadoList<String> é uma lista que contémStrings. No entanto, um tipo bruto não possui essa clareza, dificultando o trabalho com ele e com seus métodos de API.
Vamos ver a assinatura do métodoget(int index) na interfaceList para entender melhor:
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size())
*/
E get(int index);
O métodoget(int index) retorna aString na posiçãoindex no tipo parametrizadoList<String>.
No entanto, para um tipo brutoList, ele retorna umObject. Portanto, devemos fazer um esforço extra para inspecionar e identificar o tipo de elemento no tipo brutoListeadd an appropriate type-casting.. Isso pode introduzir bugs em tempo de execução, pois o tipo bruto énot type safe.
4. Não é seguro para tipos
Temos comportamento pré-genérico com tipos brutos. Portanto, um tipo brutoList aceitaObjectecan hold an element of any data type. Isso pode levar a problemas de segurança de tipo quando misturamos tipos brutos e parametrizados.
Vamos ver isso criando um código que instancia umList<String> antes de passá-lo para um método que aceita o tipo brutoListe adiciona umInteger a ele:
public void methodA() {
List parameterizedList = new ArrayList<>();
parameterizedList.add("Hello Folks");
methodB(parameterizedList);
}
public void methodB(List rawList) { // raw type!
rawList.add(1);
}
O código é compilado (com um aviso) e oInteger é adicionado ao tipo brutoList quando executado. OList<String> que foi passado como argumentonow contains a String and an Integer.
O compilador imprime um aviso devido ao uso de tipos brutos:
Note: RawTypeDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
5. Problemas em tempo de execução
A falta de segurança de tipo em um tipo bruto tem um efeito causal que pode levar a exceções no tempo de execução.
Vamos modificar o exemplo anterior para quemethodA obtenha o elemento na posição de índice 1 de nossoList<String> após chamarmethodB:
public void methodA() {
List parameterizedList = new ArrayList<>();
parameterizedList.add("Hello Folks");
methodB(parameterizedList);
String s = parameterizedList.get(1);
}
public void methodB(List rawList) {
rawList.add(1);
}
O código é compilado (com o mesmo aviso) e lança umClassCastException quando executado. Isso acontece porque o métodoget(int index) retorna umInteger, que não pode ser atribuído a uma variável do tipoString:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
6. Conclusão
Os tipos brutos são difíceis de trabalhar e podem introduzir bugs em nosso código.
Usá-los pode levar a consequências que podem ser desastrosas e, infelizmente, a maioria desses desastres acontece em tempo de execução.
Confira todos os snippets neste tutorialover on GitHub.