DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

Item 61: Dê preferência aos tipos primitivos em vez dos tipos primitivos empacotados

Tipos Primitivos vs. Tipos Primitivos Empacotados

  • Tipos Primitivos: int, double, boolean, etc.
  • Tipos Primitivos Empacotados: Integer, Double, Boolean, etc.
  • O Java possui um sistema de tipos duplo: tipos primitivos e tipos de referência (objetos).
  • Cada tipo primitivo tem um correspondente empacotado (wrapper class).

Diferenças Principais

  • Identidade vs. Valor:
    Primitivos: Não possuem identidade; dois primitivos com o mesmo valor são sempre iguais.
    Empacotados: São objetos e possuem identidade; dois objetos podem ter o mesmo valor, mas identidades diferentes.

  • Valores Nulos:
    Primitivos: Sempre têm um valor padrão (por exemplo, 0 para int).
    Empacotados: Podem ser null, o que pode levar a exceções NullPointerException se não tratados adequadamente.

  • Desempenho:
    Primitivos: Mais eficientes em termos de tempo e espaço.
    Empacotados: Introduzem overhead devido à criação de objetos adicionais.

Problemas Comuns ao Misturar Primitivos e Empacotados

  • 1. Comparação de Identidade em Vez de Valor
  • Ao comparar objetos empacotados usando ==, você está comparando referências de objeto, não os valores. Isso pode levar a resultados inesperados.

Exemplo Problemático:

Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);

Enter fullscreen mode Exit fullscreen mode

Problema: A comparação i == j compara referências, não valores.
Comportamento Incorreto: naturalOrder.compare(new Integer(42), new Integer(42)) retorna 1 em vez de 0.

Solução:
Use o método compareTo ou métodos utilitários da classe Integer.

Comparator<Integer> naturalOrder = Integer::compare;

Enter fullscreen mode Exit fullscreen mode

Ou, corrigindo o comparador original:

Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
    int i = iBoxed;
    int j = jBoxed;
    return (i < j) ? -1 : ((i == j) ? 0 : 1);
};

Enter fullscreen mode Exit fullscreen mode

2. Autounboxing e NullPointerException
Ao usar tipos empacotados que podem ser null, o autounboxing pode lançar exceções se o objeto for null.

Exemplo Problemático:

Integer i = null;
if (i == 42) {
    System.out.println("Inacreditável");
}

Enter fullscreen mode Exit fullscreen mode

Problema: i é null; ao comparar com 42, ocorre autounboxing de null, resultando em NullPointerException.
Solução: Use tipos primitivos quando possível.

int i = 0;
if (i == 42) {
    System.out.println("Inacreditável");
}

Enter fullscreen mode Exit fullscreen mode

3. Desempenho Degradado devido ao Autoboxing/Unboxing
O uso inadvertido de tipos empacotados em operações intensivas pode causar degradação de desempenho devido ao autoboxing e criação desnecessária de objetos.

Exemplo Problemático:

Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
    sum += i;
}
System.out.println(sum);

Enter fullscreen mode Exit fullscreen mode

Problema: sum é um Long empacotado; em cada iteração, ocorre autoboxing/desempacotamento.

Impacto: Código muito mais lento e uso excessivo de memória.
Solução:
Use tipos primitivos para variáveis locais em operações intensivas.

long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
    sum += i;
}
System.out.println(sum);

Enter fullscreen mode Exit fullscreen mode

Quando Usar Tipos Empacotados

  • Coleções: Não é possível usar tipos primitivos em coleções genéricas (por exemplo, List).
  • Parâmetros Genéricos: Tipos genéricos não suportam tipos primitivos (por exemplo, ThreadLocal).
  • APIs que Requerem Objetos: Certas APIs exigem objetos em vez de tipos primitivos.

Boas Práticas

  • Prefira Tipos Primitivos: Sempre que possível, use tipos primitivos para simplicidade e eficiência.
  • Cuidado com o Autoboxing/Unboxing: O autoboxing reduz a verbosidade, mas pode introduzir erros sutis.
  • Evite Comparações com == em Empacotados: Use métodos como equals() ou compare os valores desempacotados.
  • Verifique Nulos: Ao trabalhar com tipos empacotados, esteja ciente de que podem ser null e causem NullPointerException.

Resumo
Tipos Primitivos:
Mais simples e rápidos.
Não podem ser null.
Não têm identidade (apenas valor).

Tipos Empacotados:
Necessários para uso em coleções e APIs genéricas.
Podem ser null.
Têm identidade de objeto.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay