Tipos de Dados Java Explicados: Primitivos vs Referência, Casting e Classes Wrapper

.## 1. O que são os tipos de dados Java? Fundamentos e a Visão Geral

Os tipos de dados Java são um mecanismo que determina que tipo de valor uma variável pode armazenar.
Java enfatiza segurança de tipos (um design que impede operações de tipo inválidas em tempo de compilação), portanto toda variável deve ter um tipo declarado.

Por exemplo, veja o código a seguir.

int number = 10;
double price = 19.8;
String name = "Java";
  • int → apenas inteiros
  • double → apenas decimais
  • String → apenas cadeias de caracteres

Ao tornar os tipos explícitos, você obtém benefícios como:

  • Impede atribuições inválidas
  • Otimiza o uso de memória
  • Detecta bugs em tempo de compilação

Se não houvesse tipos, erros como atribuir uma string a um inteiro não seriam descobertos até a execução. Java foi projetado para evitar isso.

目次

1.1 O que é um tipo de dado? (Definição para iniciantes)

Pense em um tipo de dado como “o tipo de valores que uma variável pode manipular”.

A sintaxe básica é:

TypeName variableName = value;

Exemplo:

int age = 25;

Neste caso:

  • int é o tipo
  • age é o nome da variável
  • 25 é o valor

Essa é a relação.

Se você escrever isso, receberá um erro:

int age = "25";  // Compile-time error

Você não pode atribuir uma string a um tipo inteiro. É assim que a segurança de tipos funciona.

Armadilhas comuns para iniciantes

  • Supor que pode omitir tipos (em Java, geralmente não pode)
  • Confundir números e strings
  • Trocar = (atribuição) por == (comparação)

1.2 Categorias de tipos de dados Java (Dois tipos)

Os tipos de dados Java são amplamente divididos em duas categorias:

  1. Tipos primitivos
  2. Tipos de referência

O que são tipos primitivos?

Tipos que armazenam o valor real diretamente.
Exemplos: int, double, boolean, etc.

Características:

  • Eficientes em memória
  • Rápidos
  • Não podem conter null

O que são tipos de referência?

Tipos que não armazenam o valor em si, mas uma “referência” para onde o valor está armazenado.

Exemplo:

String text = "Hello";

String é um tipo de classe (um tipo de referência).

Características:

  • Criados a partir de classes
  • Podem ser atribuídos null
  • Possuem métodos (comportamento)

1.3 A diferença entre comportamento “Valor vs Referência”

Vamos confirmar a diferença com um exemplo simples.

int a = 10;
int b = a;
b = 20;

Neste caso:

  • a permanece 10
  • Apenas b torna‑se 20

Por outro lado, tipos de referência funcionam assim:

String s1 = "Java";
String s2 = s1;

Aqui, s1 e s2 podem referenciar o mesmo objeto (isso pode variar dependendo da implementação e otimizações).

Pontos que costumam gerar confusão

  • Entender String como um tipo primitivo
  • Supor que copiar um tipo de referência copia o valor em si
  • Não compreender como o null funciona

1.4 Por que entender tipos de dados é importante

Um entendimento fraco dos tipos de dados pode causar problemas como:

  • Resultados de cálculo inesperados
  • Overflow (estouro do intervalo de valores)
  • NullPointerException
  • Erros de conversão de tipo

Para usar Java corretamente, você deve primeiro compreender a visão geral dos tipos de dados.

2. Tipos Primitivos (Tipos de Dados Básicos): Lista e Como Usá‑los

Tipos primitivos são tipos de dados que armazenam o valor real diretamente.
Java possui 8 tipos primitivos.

CategoryTypeSizeTypical Use
Integerbyte8bitSmall integers
Integershort16bitSmaller integers
Integerint32bitStandard integers
Integerlong64bitLarge integers
Decimalfloat32bitSingle-precision floating point
Decimaldouble64bitDouble-precision floating point (standard)
Characterchar16bitA single character
Booleanbooleantrue / false

*Os tamanhos são fixados pela especificação Java (não dependem do ambiente).

2.1 Tipos Inteiros (byte / short / int / long)

Uso básico

int number = 100;
long population = 8000000000L;

Intervalos (exemplos comuns)

  • byte: -128 a 127
  • short: -32.768 a 32.767
  • int: aproximadamente ±2,1 bilhões
  • long: aproximadamente ±9,22 quintilhões

Na maioria dos casos, int é suficiente.
Raramente há necessidade prática de usar byte ou short apenas para economizar memória.

Observação importante ao usar long

long value = 10000000000L;  // L is required

Sem o L, o literal é tratado como int e pode causar erro de compilação por estar fora do intervalo.

Erros comuns

  • Estouro ao exceder o intervalo
  • Esquecer o L para literais long
  • Não perceber o estouro em cálculos de int para int

2.2 Tipos de ponto flutuante (float / double)

double price = 19.99;
float rate = 0.5f;

Regras básicas

  • Normalmente, use double
  • float requer um sufixo f
    float value = 3.14f;
    

Diferenças de precisão

  • float: cerca de 7 dígitos de precisão
  • double: cerca de 15 dígitos de precisão

Nota importante (problemas de arredondamento/precisão)

System.out.println(0.1 + 0.2);

O resultado pode não ser exatamente 0.3.
Isso se deve à representação binária de ponto flutuante.

Cálculos monetários

Para manipulação de dinheiro, double geralmente não é recomendado.
Usar BigDecimal é mais seguro.

Erros comuns

  • Usar double para dinheiro
  • Confundir float e double
  • Comparar decimais com ==

2.3 Tipo de caractere (char)

char letter = 'A';
  • Usa aspas simples
  • Gerenciado com Unicode (um padrão de codificação de caracteres)
  • Pode armazenar apenas um caractere
    char kanji = '日';
    

Erros comuns

  • Usar aspas duplas (isto é, String )
  • Tentar armazenar múltiplos caracteres

2.4 Tipo booleano (boolean)

boolean isActive = true;
  • Os valores são apenas true ou false
  • Não se pode usar 0/1 (ao contrário de C)
    boolean result = (5 > 3);
    

Erros comuns

  • Tentar atribuir um número
  • Esquecer de escrever a expressão de comparação

2.5 Observações comuns para tipos primitivos

  • Não se pode atribuir null
  • Valores padrão são definidos automaticamente para campos, mas variáveis locais devem ser inicializadas
    int x;
    System.out.println(x);  // Compile-time error (uninitialized)
    

Tipos primitivos são rápidos e leves, mas têm limitações, como não suportar null e não possuírem métodos.

3. Tipos de referência: o básico

Tipos de referência armazenam não o valor em si, mas uma referência (endereço de memória) a um objeto.
A maior diferença em relação aos tipos primitivos é que o “dado em si” e a “variável” existem separadamente.

Veja este exemplo:

String text = "Java";

Aqui, text armazena uma referência ao objeto string, não ao valor da string em si.

3.1 Tipo String (O tipo de referência mais usado)

String é um tipo de classe. Não é um tipo primitivo.

String name = "Taro";

Características

  • Imutável (não pode ser alterado)
  • Pode ser atribuído null
  • Possui métodos
    String str = "Hello";
    System.out.println(str.length());  // 5
    

Pegadinha da imutabilidade

String s = "Java";
s.concat(" SE");
System.out.println(s);  // "Java"

concat() retorna uma nova string, mas a string original não é modificada.

Uso correto:

s = s.concat(" SE");

Erros comuns

  • Assumir que String é um tipo primitivo
  • Usar == para comparação de strings
  • concatenação pesada causando problemas de desempenho (use StringBuilder)

3.2 Arrays e tipos de classe

Arrays

int[] numbers = {1, 2, 3};

Arrays também são tipos de referência.

int[] a = {1, 2};
int[] b = a;
b[0] = 99;

System.out.println(a[0]);  // 99

Como a e b referenciam o mesmo array, as alterações afetam ambos.

Tipos de classe

class Person {
    String name;
}

Person p = new Person();
p.name = "Ken";

new é a palavra‑chave usada para criar um objeto.

3.3 O que é null?

null representa um estado onde “não há objeto referenciado”.

String text = null;

Chamar um método quando uma referência é null causa um erro.

text.length();  // NullPointerException

Isso é chamado de NullPointerException (NPE).

Como lidar com null

if (text != null) {
    System.out.println(text.length());
}

3.4 A diferença entre == e equals()

== (comparação de referência)

.

equals() (comparação de conteúdo)

Compara se o conteúdo é o mesmo.

String a = new String("Java");
String b = new String("Java");

System.out.println(a == b);        // false
System.out.println(a.equals(b));   // true

Erros comuns

  • Usar == para comparação de strings
  • Chamar equals() sem verificar se é null
  • Confundir cópia de referências com cópia de valores

3.5 Resumo rápido: Diferenças em relação aos tipos primitivos

ItemPrimitive TypesReference Types
StoresThe value itselfA reference
nullNot allowedAllowed
MethodsNoYes
newNot neededUsually needed

Tipos de referência são flexíveis, mas você deve ter cuidado ao lidar com null e referências compartilhadas.

4. Classes Wrapper e Autoboxing

Classes wrapper são classes que permitem tratar valores primitivos como objetos.
Em Java, coleções (como List e Map) só podem armazenar tipos de referência, portanto não é possível armazenar primitivos diretamente. As classes wrapper existem para esse fim.

4.1 Classes Wrapper comuns

Primitive TypeWrapper Class
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

Exemplo:

Integer number = 10;
Double price = 19.99;

Como as classes wrapper são tipos de referência, elas podem conter null.

Integer value = null;  // OK

4.2 O que é Autoboxing?

Boxing significa converter um tipo primitivo em uma classe wrapper.

Desde o Java 5, essa conversão pode acontecer automaticamente.

Integer num = 10;  // autoboxing

Internamente, isso equivale a:

Integer num = Integer.valueOf(10);

4.3 O que é Unboxing?

Unboxing converte uma classe wrapper de volta a um tipo primitivo.

Integer num = 20;
int value = num;  // auto-unboxing

Internamente:

int value = num.intValue();

4.4 Quando você precisa de Classes Wrapper

1. Ao usar coleções

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);  // autoboxing

Não é possível usar ArrayList<int>.

2. Quando você precisa lidar com null

Integer score = null;

Tipos primitivos não podem ser null.

4.5 Notas e Erros Comuns

1. Exceção ao fazer unboxing de null

Integer num = null;
int value = num;  // NullPointerException

Uma exceção ocorre durante o auto‑unboxing.

2. Comparando com ==

Integer a = 1000;
Integer b = 1000;

System.out.println(a == b);  // may be false

Como esses são objetos, == compara referências.
Use equals() para comparação de conteúdo.

a.equals(b);

3. Impacto de desempenho

Classes wrapper podem envolver criação de objetos,
portanto cálculos intensivos podem ser mais lentos que usar tipos primitivos.

4.6 Escolhendo entre Tipos Primitivos e Classes Wrapper

  • Cálculos numéricos → tipos primitivos
  • Armazenamento em coleções → classes wrapper
  • Manipulação de null → classes wrapper

Se você lembrar dessas diretrizes, não hesitará no trabalho real.

5. Conversão de Tipo (Casting): O Básico

Em Java, quando você trabalha com valores entre diferentes tipos de dados, usa conversão de tipo (casting).
Existem dois tipos principais:

  • Conversão implícita (widening conversion)
  • Conversão explícita (narrowing conversion)

5.1 Conversão Implícita (Widening)

Conversões de um tipo de alcance menor para um tipo de alcance maior acontecem automaticamente.

int num = 100;
long bigNum = num;  // automatic conversion

Isso é seguro porque expande o intervalo numérico.

Ordem de conversão (exemplo relacionado a inteiros)

byte → short → int → long → float → double

Exemplo

int a = 10;
double b = a;  // OK

Notas

  • A precisão é preservada em muitos casos, mas pode haver arredondamento com float ou double.
  • char pode ser convertido como um valor inteiro.
    char c = 'A';
    int code = c;  // 65
    

5.2 Conversão Explícita (Narrowing)

Ao converter de um tipo maior para um tipo menor, é necessário fazer cast explicitamente.

double price = 19.99;
int rounded = (int) price;

O resultado é:

rounded = 19

A parte fracionária é truncada.

Sintaxe

(TargetType) variable

5.3 Exemplo de Perda de Dados

int big = 1000;
byte small = (byte) big;
System.out.println(small);

O resultado não é “imprevisível”, mas sim ajustado para caber dentro da faixa alvo.
Aqui, 1000 excede o intervalo de byte, portanto o valor é alterado.

Conceitos errôneos comuns

  • Pensar que isso causará um erro → na realidade, o valor é alterado
  • Supor que é sempre seguro → pode ocorrer perda de dados

5.4 Uma Armadilha: Divisão Inteira

int a = 5;
int b = 2;
double result = a / b;
System.out.println(result);

O resultado é:

2.0

A divisão inteira é realizada como uma operação inteira.

Abordagem correta:

double result = (double) a / b;

Resultado:

2.5

5.5 Observações sobre Comparação de Decimais

double x = 0.1 + 0.2;
System.out.println(x == 0.3);  // may be false

Isso se deve a problemas de precisão de ponto flutuante.

Uma comparação mais segura

Math.abs(x - 0.3) < 0.000001

5.6 Casting de Tipos de Referência

Você também pode fazer casting de tipos de referência (quando há uma relação de herança).

Object obj = "Java";
String str = (String) obj;

Fazer casting para um tipo incorreto causa uma exceção.

Integer num = (Integer) obj;  // ClassCastException

Resumo de Erros Comuns

  • Conversões fora do intervalo alteram valores
  • Não perceber a divisão inteira
  • Comparar decimais com ==
  • Forçar casts de referência inválidos

Casting frequentemente não gera erros de compilação, portanto mal‑entendidos podem facilmente gerar bugs.

6. Guia Prático de Seleção de Tipos (Para Você Não Hesitar no Trabalho)

Agora que você entende como os tipos de dados em Java funcionam, uma pergunta comum no mundo real é: “Qual tipo devo usar?” Esta seção organiza critérios de decisão práticos.

6.1 Por que int e double geralmente são suficientes

Use int para inteiros (por padrão)

int count = 100;

Razões:

  • O intervalo de 32 bits é suficiente para a maioria dos casos
  • Mais fácil para a JVM otimizar
  • Legível e padrão

Normalmente você não precisa forçar o uso de byte ou short.
Escolher tipos menores apenas para economizar memória geralmente é apenas para casos especiais (como arrays enormes).

Use double para decimais (por padrão)

double rate = 0.75;

Ele tem maior precisão que float e é a escolha padrão.
A menos que você tenha um motivo claro, escolha double.

6.2 Por que Você Deve Usar BigDecimal para Dinheiro

Este código é arriscado para dinheiro:

double price = 0.1 + 0.2;

Devido a erros de ponto flutuante, você pode não obter um valor exato.

Abordagem correta:

import java.math.BigDecimal;

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal result = a.add(b);

Por que passar strings?

new BigDecimal(0.1);  // not recommended

Criar a partir de um double pode carregar seu erro de precisão.

Erros comuns

  • Manipular dinheiro com double
  • Usar new BigDecimal(doubleValue)
  • Esquecer regras de arredondamento

6.3 Coleções Requerem Classes Wrapper

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);

Você não pode usar tipos primitivos diretamente.

ArrayList<int> list;  // Compile-time error

Razão:

  • Generics (coleções tipadas) suportam apenas tipos de referência

6.4 Decida com Base na Necessidade de null

Não precisa de null → tipos primitivos

int age = 0;

Precisa de null → classes wrapper

Integer age = null;

Em integrações de banco de dados ou entradas de formulário, pode ser necessário lidar com null.

6.5 Diretrizes Básicas de Performance

  • Cálculos → tipos primitivos
  • Coleções → classes wrapper
  • Evite criar wrappers dentro de loops apertados

Exemplo (não recomendado):

for (Integer i = 0; i < 1000000; i++) { }

Usar tipos primitivos é mais eficiente.

6.6 Tabela Resumo: Tipos Recomendados por Caso de Uso

Use CaseRecommended Type
Typical integersint
Typical decimalsdouble
MoneyBigDecimal
Boolean checksboolean
StringsString
Storing in collectionsWrapper classes

Erros Comuns no Mundo Real

  • Escolher tipos desnecessariamente pequenos
  • Usar double para dinheiro
  • Projetar sem considerar null
  • Exceções de auto-unboxing de classes wrapper

A seleção de tipos é uma parte central do design. Se você prosseguir com ambiguidade, o custo de corrigir problemas mais tarde aumenta significativamente.

7. Resumo dos Tipos de Dados Java (Com Tabelas)

Vamos resumir tudo em um formato que responda rapidamente à intenção de busca comum.
Os tipos de dados Java são divididos em “tipos primitivos” e “tipos de referência.”

7.1 Lista de Tipos Primitivos

TypeSizeDefault (fields)Typical Use
byte8bit0Small integers
short16bit0Smaller integers
int32bit0Standard integers
long64bit0LLarge integers
float32bit0.0fSingle-precision floating point
double64bit0.0dStandard floating point
char16bit‘\u0000’A single character
booleanfalseBoolean value

*Variáveis locais não são inicializadas automaticamente.

Pontos‑chave

  • Para cálculos numéricos, use int / double por padrão
  • Para dinheiro, use BigDecimal
  • null não é permitido
  • Sem métodos

7.2 Visão Geral dos Tipos de Referência

Tipos de referência típicos:

  • String
  • Arrays (ex., int[] )
  • Tipos de classe (classes personalizadas)
  • Classes wrapper (ex., Integer )
  • Coleções (List, Map, etc.)

Resumo das características

ItemReference Types
Can assign nullYes
MethodsAvailable
new keywordUsually needed
Comparisonequals() recommended

7.3 Comparação Final: Primitivo vs Referência

PerspectivePrimitive TypesReference Types
StoresDirectlyBy reference
Memory efficiencyHighSomewhat lower
nullNoYes
SpeedFastSomewhat slower
Main useCalculationsObject handling

7.4 O Conjunto Mínimo que Iniciantes Devem Aprender Primeiro

Comece com estes quatro tipos:

  • int
  • double
  • String
  • boolean

Com eles, você pode criar programas básicos.

7.5 Erros Gerais Comuns

  1. Comparar String com ==
  2. Usar double para dinheiro
  3. Não perceber a divisão inteira
  4. Esquecer verificações de null
  5. Esquecer o L para literais long
  6. Desembalar (unboxing) null em classes wrapper

Evitar esses erros por si só reduzirá significativamente os erros de iniciantes.

7.6 Conclusões Finais

  • Java é uma linguagem segura em termos de tipos
  • Compreender os tipos de dados é a base de todo código
  • Tipos primitivos são para cálculos rápidos
  • Tipos de referência são para gerenciar objetos
  • Escolher o tipo correto afeta diretamente a qualidade

Perguntas Frequentes

Q1. Quantos tipos de dados Java existem?

Resposta:
Existem 8 tipos primitivos. Os tipos de referência podem ser inúmeros (classes, arrays, interfaces, etc.). É importante primeiro entender os 8 tipos primitivos.

Q2. O String é um tipo primitivo?

Resposta:
Não. String é um tipo de classe (um tipo de referência). Ele é tratado como um objeto e pode receber null.

Q3. Qual a diferença entre int e Integer?

Resposta:
int é um tipo primitivo. Integer é uma classe wrapper (um tipo de referência). Integer pode conter null, mas o auto-unboxing pode lançar uma exceção.

Q4. Posso usar double para cálculos monetários?

Resposta:
Tecnicamente sim, mas não é recomendado. Problemas de precisão de ponto flutuante podem ocorrer, portanto usar BigDecimal é mais seguro.

Q5. Por que a divisão de inteiros não produz um decimal?

Resposta:
Porque as operações inteiras são realizadas usando tipos inteiros, a parte fracionária é truncada. Se precisar de um resultado decimal, converta um operando para double.

Q6. O que é null?

Resposta:
Representa um estado onde nenhum objeto está referenciado. Chamar um método em null causa um NullPointerException.

Q7. Qual a diferença entre == e equals()?

Resposta:
== compara referências (endereços de memória). equals() compara conteúdo. Para comparação de strings, use equals().

Q8. Quais tipos os iniciantes devem aprender primeiro?

Resposta:
Priorize int, double, String e boolean. Estes são os tipos centrais mais usados no trabalho real.