Tipos brutos em Java

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:

  1. Eles não são expressivos

  2. Eles não têm segurança de tipo e

  3. 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.